Basic Loop Implementation with Iteration Counts
Summary
Implement basic loop functionality that allows executing a state multiple times with a fixed iteration count.
Motivation
Currently, testing scenarios that require repeating requests (e.g., "redeem coupon 10 times") requires duplicating state definitions or running the attack multiple times manually. This leads to:
- Verbose, hard-to-maintain YAML configurations
- Inability to model brute-force or exhaustive testing scenarios
- Poor user experience for common attack patterns
Proposed Syntax
states:
redeem_multiple_times:
description: "Attempt to redeem coupon multiple times"
request: |
POST /api/redeem-coupon
Authorization: Bearer {{ token }}
{"coupon_code": "SUMMER2024"}
loop:
iterations: 10
next:
- on_status: 200
goto: verify_redemptions
- on_loop_complete:
goto: end
Requirements
Functional Requirements
-
Fixed Iteration Count
- Support
iterations parameter (integer, minimum 1)
- Execute state exactly N times
- Maintain execution order (sequential by default)
-
Loop Completion Detection
- Trigger
on_loop_complete transition when all iterations finish
- Support mixing loop completion with status-based transitions
-
Request Execution
- Each iteration should render the request template independently
- Support using extracted variables from previous iterations
- Maintain separate response context for each iteration
Non-Functional Requirements
-
Performance
- Minimal overhead compared to manually duplicated states
- Memory-efficient for loops with 1000+ iterations
- Support for streaming results (don't load all responses in memory)
-
Error Handling
- Continue loop on errors by default
- Support
stop_on_error flag (optional)
- Collect and report all errors at loop completion
-
Observability
- Log each iteration with iteration number
- Track success/failure rate across iterations
- Report timing statistics (min, max, avg, p95, p99)
Implementation Details
State Configuration Schema
{
"properties": {
"loop": {
"type": "object",
"properties": {
"iterations": {
"type": "integer",
"minimum": 1,
"maximum": 10000,
"description": "Number of times to execute this state"
},
"stop_on_error": {
"type": "boolean",
"default": false,
"description": "Stop loop if any request fails"
},
"parallel": {
"type": "boolean",
"default": false,
"description": "Execute iterations in parallel (Phase 4 feature)"
}
},
"required": ["iterations"]
}
}
}
Internal Execution Flow
class LoopExecutor:
def execute_loop_state(self, state_config, context):
loop_config = state_config.get('loop', {})
iterations = loop_config.get('iterations')
stop_on_error = loop_config.get('stop_on_error', False)
results = []
for i in range(iterations):
# Update loop context
context['loop'] = {
'index': i,
'iteration': i + 1 # Reserved for future
}
# Execute single iteration
try:
result = self.execute_single_request(state_config, context)
results.append(result)
# Check for early exit conditions
if stop_on_error and not result.success:
break
except Exception as e:
if stop_on_error:
raise
results.append(LoopIterationError(iteration=i, error=e))
# Determine next transition
return self.resolve_loop_transition(state_config, results, context)
Transition Logic
- Status-based transitions checked on LAST iteration only
- on_loop_complete triggered after all iterations
- Priority: status transitions > loop_complete > default next
def resolve_loop_transition(self, state_config, results, context):
last_result = results[-1]
# Check status-based transitions using last iteration
for transition in state_config.get('next', []):
if 'on_status' in transition:
if last_result.status == transition['on_status']:
return transition['goto']
# Check loop_complete transition
for transition in state_config.get('next', []):
if 'on_loop_complete' in transition:
return transition['goto']
# Default
return state_config.get('next', [{}])[0].get('goto')
Testing Requirements
Unit Tests
Integration Tests
Performance Tests
Output Example
======================================================================
LOOP STATE: redeem_multiple_times
======================================================================
Iterations: 10
Stop on error: false
======================================================================
[Iteration 1/10] Status: 200, Time: 45.2ms ✓
[Iteration 2/10] Status: 200, Time: 46.1ms ✓
[Iteration 3/10] Status: 200, Time: 44.8ms ✓
[Iteration 4/10] Status: 409, Time: 43.2ms ✗ (Conflict)
[Iteration 5/10] Status: 409, Time: 42.9ms ✗ (Conflict)
...
======================================================================
LOOP RESULTS
======================================================================
Total iterations: 10
Successful: 3 (30%)
Failed: 7 (70%)
Timing Statistics:
Average: 45.1ms
Min: 42.9ms
Max: 48.3ms
p95: 47.8ms
p99: 48.3ms
⚠ VULNERABLE: 3 successful redemptions detected!
Expected: 1 (first request should succeed, rest should fail)
Actual: 3 (race condition or validation bug)
======================================================================
Documentation Updates
Migration Path
Existing configurations continue to work unchanged. New loop syntax is opt-in.
Before (duplicated states):
states:
redeem_1: { request: "...", next: [{goto: redeem_2}] }
redeem_2: { request: "...", next: [{goto: redeem_3}] }
redeem_3: { request: "...", next: [{goto: end}] }
After (with loops):
states:
redeem_multiple:
request: "..."
loop:
iterations: 3
next:
- on_loop_complete:
goto: end
Acceptance Criteria
Follow-up Issues
- #XX - Loop Context Variables (index, counter, first, last) - Phase 1.2
- #XX - Early Loop Exit with break_on Conditions - Phase 1.3
- #XX - Inter-iteration Delays - Phase 1.4
Related Issues
- Depends on: None (standalone feature)
- Blocks: All other Phase 1 issues
- Related to: JSON Schema Validation (#XX)
Basic Loop Implementation with Iteration Counts
Summary
Implement basic
loopfunctionality that allows executing a state multiple times with a fixed iteration count.Motivation
Currently, testing scenarios that require repeating requests (e.g., "redeem coupon 10 times") requires duplicating state definitions or running the attack multiple times manually. This leads to:
Proposed Syntax
Requirements
Functional Requirements
Fixed Iteration Count
iterationsparameter (integer, minimum 1)Loop Completion Detection
on_loop_completetransition when all iterations finishRequest Execution
Non-Functional Requirements
Performance
Error Handling
stop_on_errorflag (optional)Observability
Implementation Details
State Configuration Schema
{ "properties": { "loop": { "type": "object", "properties": { "iterations": { "type": "integer", "minimum": 1, "maximum": 10000, "description": "Number of times to execute this state" }, "stop_on_error": { "type": "boolean", "default": false, "description": "Stop loop if any request fails" }, "parallel": { "type": "boolean", "default": false, "description": "Execute iterations in parallel (Phase 4 feature)" } }, "required": ["iterations"] } } }Internal Execution Flow
Transition Logic
Testing Requirements
Unit Tests
stop_on_errorstops on first failurestop_on_error=falseIntegration Tests
Performance Tests
Output Example
Documentation Updates
Migration Path
Existing configurations continue to work unchanged. New
loopsyntax is opt-in.Before (duplicated states):
After (with loops):
Acceptance Criteria
loop.iterationsparameter works as documentedon_loop_completetransition triggers correctlystop_on_errorflag works as expectedFollow-up Issues
Related Issues