Documentation / SwarmHack

Tuning & Troubleshooting

Operational Tuning

Parallelism

KillChainOrchestrator creates an agent-pool coordinator with a 64-slot semaphore. The 25→64 raise in v2.6.0 closed a deadlock against the 28-agent full-discovery fan-out. Not currently a CLI flag.

Rate limiting

GlobalRateLimiter::new(50, 50.0)50 concurrent in-flight requests, 50 req/s token bucket. Per-agent overrides read from config/swarmhack.yaml rate_limiting: block (default requests_per_second: 10, burst_size: 20). For WAF-friction targets, use the more conservative config/pentest_rate_limited.yaml (requests_per_second: 5, burst_size: 10) via --config.

Timeouts

Per-request HTTP timeouts floored at 10 s and capped at 30 s.

| Agent / vuln type | HTTP per-request (s) |

| --- | --- |

| SQLInjection | 20 |

| XSS, CSRF, IDOR, AuthBypass, WebCrawler, CommandInjection | 10 |

| HTTPSmuggling | 15 |

| DefaultCredentials, PrivilegeEscalation, LateralMovement | 30 |

| LdapSpray, LdapEnum, SmbEnum, KerberosAttack, Kerbrute, AuthCoercion, NtlmDowngrade, TLSVulnerability | 15 |

Adjust --timeout for the whole mission budget (default 3600 s).

GOAP planner

A* planner with a HashSet<WorldState> closed-set, parent-pointer path reconstruction, and goal-scoped action pruning. Opt in to A* for phase planning with --use-goap-planning.

Logging

Default: ./logs/{session-uuid}.jsonl, rotated at 100 MB, retained 30 days.

| Flag / env | Default | Effect |

| --- | --- | --- |

| --log-level <LVL> | info | trace, debug, info, warn, error. |

| --log-dir <PATH> | ./logs | Output directory. |

| --log-max-size-mb <N> | 100 | Rotate threshold. |

| --log-retention-days <N> | 30 | Compressed retention. |

| --log-file <PATH> | auto | Custom path. |

| --no-file-logging | off | Stdout only. |

| RUST_LOG | swarmhack=info | tracing-subscriber env filter; takes precedence over --log-level. |

Troubleshooting

| Symptom | Likely cause | Fix |

| --- | --- | --- |

| ERROR: Cannot Connect to Prancer Portal | Token expired, network blocked, wrong portal URL. | Re-issue token; verify --portal-url; check DNS / proxy. |

| ERROR: Invalid Token | Token is not 32 hex chars. | Copy the full token; strip whitespace. |

| ERROR: Invalid Customer | Wrong case or prancer- prefix. | Use the lowercase tenant slug (xforia, not XFORIA or prancer-xforia). |

| Exit status 2 immediately | No --authz-doc and no opt-out. | Pass --authz-doc <PATH>; or --authz-skip AND SWARMHACK_ALLOW_NO_AUTHZ=1. |

| Exit status 3 immediately | Target is not in authz-doc targets[]. | Add the host (label-strict). |

| Target '…' is public; --allow-public required | Non-RFC1918 / non-loopback target without the opt-in. | Pass --allow-public AND confirm the host is in authz-doc targets[]. |

| authz doc … expired | Doc expires_at past Now. | Reissue with a new expires_at ≤ 24 h ahead. |

| TLS handshake failures against a lab cert | Self-signed cert; default TLS verification. | Lab only: SWARMHACK_INSECURE_PREFLIGHT_TLS=1 SWARMHACK_INSECURE_BANNER_TLS=1. Never set in production. |

| Agent pool exhausted / mission stalls | Pre-v2.6.0 semaphore deadlock. | Upgrade to v2.6.0 — pool raised to 64, acquire_slot bounded at 30 s. |

| Mission completes with 0 findings | Well-hardened target, wrong agent set, aggressive WAF. | Try --agents crawler,sqli,xss; --rate-limit 5; use config/pentest_rate_limited.yaml. |

| agents that found nothing in summary | Correct behaviour — agents emit zero when nothing is exploitable. | No action; documented as a feature. |

| NTLM relay agent emits "skip" finding | Default-deny; --allow-ntlm-relay not set. | Confirm engagement letter authorises NTLM relay, then re-run with the flag. |

| ZerOlogon refuses host even with X8 bypass | Per-host scope gate (defence in depth). | Add the DC host to authz-doc targets[]. |

| Reports written but no SSE Markdown | --report does not list sse. | Pass --report sse; it auto-promotes to sse,ocsf,html. |

| swarmhack lint --pentest-mode exits 1 | Finding has no crown jewel or severity_id < 3. | Inspect the finding; upgrade evidence trail or accept the linter's invariant. |