Loop Context Variables (index, counter, first, last)
Summary
Provide loop iteration context variables (loop.index, loop.counter, loop.first, loop.last) accessible in request templates and conditionals.
Motivation
When executing loops, attack scenarios often need to:
- Use the iteration number in requests (e.g., testing sequential IDs)
- Treat the first iteration differently (e.g., setup)
- Treat the last iteration differently (e.g., cleanup)
- Display human-friendly iteration numbers in logs
Current limitation: No way to access iteration information within templates.
Proposed Syntax
states:
test_user_enumeration:
description: "Test sequential user IDs"
request: |
GET /api/users/{{ loop.counter }}
Authorization: Bearer {{ token }}
loop:
iterations: 100
logger:
on_thread_enter: |
{% if loop.first %}
Starting user enumeration attack...
{% endif %}
Testing user ID: {{ loop.counter }}
on_thread_leave: |
{% if loop.last %}
Completed user enumeration. Found {{ valid_users | length }} users.
{% endif %}
extract:
user_exists:
type: jpath
pattern: "$.exists"
next:
- on_loop_complete:
goto: analyze_results
Loop Context Variables
loop.index
- Type: Integer
- Range: 0 to (iterations - 1)
- Description: Zero-based iteration index
- Use case: Array/list access, algorithmic calculations
request: |
POST /api/test
{"value": {{ test_values[loop.index] }}}
loop.counter
- Type: Integer
- Range: 1 to iterations
- Description: Human-friendly iteration counter
- Use case: User IDs, sequential numbering, logs
request: |
GET /api/users/{{ loop.counter }}
loop.first
- Type: Boolean
- Value:
true on first iteration, false otherwise
- Description: True only on first iteration (index=0)
- Use case: Initialization, setup requests
logger:
on_thread_enter: |
{% if loop.first %}
🚀 Starting attack sequence...
{% endif %}
loop.last
- Type: Boolean
- Value:
true on last iteration, false otherwise
- Description: True only on last iteration (index=iterations-1)
- Use case: Cleanup, final validation, summaries
logger:
on_thread_leave: |
{% if loop.last %}
✅ Attack complete. Total requests: {{ loop.counter }}
{% endif %}
loop.iteration (alias)
- Type: Integer
- Description: Alias for
loop.counter (for clarity)
- Note: Use
loop.counter for consistency
Implementation Details
Loop Context Structure
@dataclass
class LoopContext:
"""Context information for current loop iteration."""
index: int # 0-based index
counter: int # 1-based counter
iteration: int # Alias for counter
first: bool # True on first iteration
last: bool # True on last iteration
total: int # Total iterations
@staticmethod
def create(index: int, total: int) -> 'LoopContext':
return LoopContext(
index=index,
counter=index + 1,
iteration=index + 1,
first=(index == 0),
last=(index == total - 1),
total=total
)
Template Context Injection
class LoopExecutor:
def execute_loop_state(self, state_config, context):
iterations = state_config['loop']['iterations']
for i in range(iterations):
# Inject loop context
loop_context = LoopContext.create(i, iterations)
context['loop'] = {
'index': loop_context.index,
'counter': loop_context.counter,
'iteration': loop_context.iteration,
'first': loop_context.first,
'last': loop_context.last,
'total': loop_context.total,
}
# Render request with loop context available
rendered_request = self.template_engine.render(
state_config['request'],
context
)
# Execute request...
Jinja2 Template Examples
{# Access in conditionals #}
{% if loop.first %}
"action": "initialize"
{% elif loop.last %}
"action": "finalize"
{% else %}
"action": "process"
{% endif %}
{# Use in expressions #}
"item_id": "{{ 1000 + loop.index }}",
"batch": "{{ (loop.index // 10) + 1 }}",
"is_final": {{ loop.last | lower }}
{# Logging #}
Progress: {{ loop.counter }}/{{ loop.total }} ({{ (loop.counter / loop.total * 100) | round }}%)
Use Cases
1. User Enumeration
states:
enumerate_users:
request: |
GET /api/users/{{ loop.counter }}
loop:
iterations: 1000
2. Batch Processing
states:
process_batches:
request: |
POST /api/batch
{
"batch_id": {{ (loop.index // 100) + 1 }},
"items": {{ items[loop.index:loop.index+100] | tojson }}
}
loop:
iterations: 10
3. Progressive Load Testing
states:
load_test:
description: "Increase load progressively"
request: |
POST /api/heavy-endpoint
{"load_factor": {{ loop.counter * 10 }}}
logger:
on_thread_enter: |
{% if loop.first %}
Starting load test...
{% endif %}
Load factor: {{ loop.counter * 10 }}
loop:
iterations: 50
4. Setup and Cleanup
states:
attack_with_setup:
request: |
{% if loop.first %}
POST /api/setup
{"initialize": true}
{% elif loop.last %}
POST /api/cleanup
{"finalize": true}
{% else %}
POST /api/attack
{"payload": "malicious"}
{% endif %}
loop:
iterations: 10
5. Array Iteration
entrypoints:
- state: test_coupons
input:
coupons: ["SAVE10", "SAVE20", "SUMMER2024", "WINTER2024"]
states:
test_coupons:
request: |
POST /api/apply-coupon
{"code": "{{ coupons[loop.index] }}"}
loop:
iterations: "{{ coupons | length }}"
logger:
on_thread_enter: |
[{{ loop.counter }}/{{ loop.total }}] Testing: {{ coupons[loop.index] }}
Testing Requirements
Unit Tests
Integration Tests
Edge Cases
Output Examples
Progress Logging
[Iteration 1/100] Testing user ID: 1 ✓ (exists)
[Iteration 2/100] Testing user ID: 2 ✗ (not found)
[Iteration 3/100] Testing user ID: 3 ✓ (exists)
...
[Iteration 100/100] Testing user ID: 100 ✗ (not found)
✅ Completed. Found 47 valid users.
Conditional Execution
[Iteration 1/10] 🚀 Initializing attack...
[Iteration 2/10] 📤 Sending payload...
[Iteration 3/10] 📤 Sending payload...
...
[Iteration 10/10] 🧹 Cleaning up...
✅ Attack complete.
Documentation Updates
Schema Updates
No schema changes required. Loop context is automatically available when loop is defined.
Acceptance Criteria
Follow-up Issues
- #XX - Early Loop Exit with break_on Conditions - Phase 1.3
- #XX - Inter-iteration Delays - Phase 1.4
Related Issues
- Depends on: #XX Basic Loop Implementation
- Blocks: #XX Early Loop Exit (needs loop.index for conditions)
- Related to: Template Engine improvements
Loop Context Variables (index, counter, first, last)
Summary
Provide loop iteration context variables (
loop.index,loop.counter,loop.first,loop.last) accessible in request templates and conditionals.Motivation
When executing loops, attack scenarios often need to:
Current limitation: No way to access iteration information within templates.
Proposed Syntax
Loop Context Variables
loop.indexloop.counterloop.firsttrueon first iteration,falseotherwiseloop.lasttrueon last iteration,falseotherwiseloop.iteration(alias)loop.counter(for clarity)loop.counterfor consistencyImplementation Details
Loop Context Structure
Template Context Injection
Jinja2 Template Examples
Use Cases
1. User Enumeration
2. Batch Processing
3. Progressive Load Testing
4. Setup and Cleanup
5. Array Iteration
Testing Requirements
Unit Tests
loop.indexstarts at 0 and increments correctlyloop.counterstarts at 1 and increments correctlyloop.firstis true only on first iterationloop.lastis true only on last iterationloop.iterationequalsloop.counter(alias)loop.totalreflects total iterationsIntegration Tests
Edge Cases
Output Examples
Progress Logging
Conditional Execution
Documentation Updates
Schema Updates
No schema changes required. Loop context is automatically available when
loopis defined.Acceptance Criteria
loop.firstandloop.lastwork correctlyFollow-up Issues
Related Issues