Safety Rules¶
All engagements must comply with these safety rules. Violations risk legal liability, data loss, and service disruption. These rules are enforced at every level: skill boilerplate, scope checking, and the /pentest orchestrator.
Authorization Requirement¶
Mandatory Before ANY Testing
Before executing any test, confirm all three of the following:
- Written authorization -- a signed contract, active bug bounty program, or proof of self-ownership
- Defined scope -- explicit list of in-scope URLs, domains, and IP ranges (documented in
scope.txt) - Agreed rules of engagement -- rate limits, testing windows, excluded endpoints, escalation contacts
Testing without authorization is illegal under most jurisdictions (CFAA, CMA, etc.).
13 Critical Safety Rules¶
These rules are absolute and apply to every phase, every skill, and every request.
Rule 1: Never Perform Destructive Actions¶
No DELETE, DROP, TRUNCATE, or any data-modifying operation on the target. All SQL injection payloads must be SELECT-only. Never alter, remove, or corrupt production data.
Rule 2: Never Cause Denial of Service¶
No flood attacks, resource exhaustion, zip bombs, billion-laughs XML, or recursive payloads. All testing must leave the target operational.
Rule 3: Never Exfiltrate Real Data¶
Document one example of data exposure and stop. Never download full databases, user lists, or PII dumps. A single row proving the vulnerability is sufficient evidence.
Rule 4: Never Modify Production Data¶
SQL injection: SELECT and SLEEP()/BENCHMARK() only. XSS: alert(document.domain) or console.log() only. Never insert, update, or delete records.
Rule 5: Always Confirm Scope¶
Only test URLs and domains explicitly listed in scope.txt. Scope enforcement is implemented at the tool level via scope_curl() -- every outbound request is validated against the scope file. Redirects are followed only if each hop remains in scope.
Rule 6: Always Warn Before Risky Actions¶
Prompt the user for explicit confirmation before any action that could write data, send emails, lock accounts, or trigger side effects on the target.
Rule 7: Enforce Rate Limits¶
| Activity | Maximum Rate |
|---|---|
| Scanning (nuclei, nikto) | 10 req/sec |
| Fuzzing (ffuf, wordlists) | 50 req/sec |
| Authentication testing | 1 req/sec |
In stealth mode (default), rates are further reduced. See Stealth Mode for per-tool configurations.
Rule 8: Stop on WAF Detection¶
Immediately halt the current test phase if any of the following are received:
- HTTP
429 Too Many Requests - HTTP
503 Service Unavailable - WAF ban page or CAPTCHA challenge
The stealth_curl() function implements automatic backoff on 429 responses, scaled by JITTER_MULT.
Rule 9: Log Everything¶
Every request, response, and finding must be logged. Structured logging writes to logs/pentest-timeline.jsonl using log_event() and log_finding() from the shared boilerplate. This creates an auditable trail of all testing activity.
Rule 10: Verify Before Reporting¶
Every finding requires a working, reproducible exploit plus real evidence. If an exploit attempt fails, the finding is not reported. The /verify phase re-executes all PoCs to eliminate false positives.
For pentests, HTTP-backed findings require the full raw HTTP request and the full raw HTTP response, including status line, complete headers, and complete body. The same material must survive all downstream outputs: FINDING-NNN.md, HedgeDoc/Outline notes, and generated .docx reports. Summary-only evidence or truncated responses are not acceptable as the default report standard.
For bug bounty submissions, use the fastest reproducible PoC, preferably curl, and collect representative screenshots when the issue is visual. A working-PoC video is mandatory for bug bounty findings.
Rule 11: Never Use Past Engagement Data During Active Testing¶
Historical results in evals/labs/*/history/ and gap-analysis.md exist only for retrospective analysis. During /pentest, every engagement starts fresh with standard discovery, recon, and testing. Zero influence from past targets.
Rule 12: Never Read Files Outside the Project Root¶
During /pentest, all information about the target must come from:
- (a) The target itself via HTTP requests
- (b)
lab-config.jsoninevals/labs/ - (c) The user providing it
Never read READMEs, source code, or config files from the target's local directory (e.g., ../vulnhr/README.md). This violates black-box testing methodology and invalidates results.
Rule 13: Always Fix Problems Before Proceeding¶
If a tool fails (wrong flags, broken pipe, missing dependency), diagnose and fix the root cause before continuing to the next step. Document the fix in CLAUDE.md. Never skip a failed step and move on.
Non-Destructive Verification Techniques¶
All verification must use safe, non-destructive methods:
| Vulnerability | Safe Verification Method |
|---|---|
| SQL Injection | SELECT, SLEEP(), BENCHMARK() only |
| XSS | alert(document.domain) or console.log() only |
| SSRF | OOB via collaborator / webhook.site -- never attack internal services |
| Command Injection | whoami, id, hostname, sleep only |
| File Upload | Benign test files only |
| Race Conditions | 2-3 parallel requests maximum |
| Authentication | Use provided test credentials -- never brute force |
Stored Payload Cleanup¶
Mandatory for Persistent Payloads
After confirming a stored/persistent vulnerability and collecting all evidence (full HTTP request+response, representative screenshot when relevant), clean up the injected payload using cleanup_stored_payload(). Verify cleanup succeeded. This applies to: stored XSS, stored SSTI, stored CRLF, persistent comment/profile injection, Mermaid injection, and any payload that renders for other users.
Findings must include cleanup_status set to cleaned or not_applicable.
Mandatory User Confirmation¶
The following actions require explicit user confirmation before execution, as they may have irreversible effects on production systems:
- Cache poisoning
- Request smuggling
- Race conditions
- Business logic testing (cart/payment manipulation)
- Port scanning (via naabu)
- sqlmap execution
- Mass assignment testing
- Password reset with Host header injection
Never Run
Account lockout testing is never permitted. It causes denial of service to legitimate users and is explicitly prohibited.
Scope Enforcement Architecture¶
Scope is enforced at the tool level, not just by policy. The scope-check.md helper provides:
load_scope()-- parsesscope.txtinto include/exclude arrays at skill startupis_in_scope(url)-- validates any URL against the scope, supporting wildcards (*.example.com) and path-based patternsscope_curl()-- drop-in replacement forcurlthat blocks out-of-scope requestsscope_curl_follow()-- follows redirects while validating each hop stays in scope
# Example: scope-enforced request
scope_curl "https://target.example.com/api/users" --max-time 10
# Example: redirect-safe request (validates each 3xx hop)
scope_curl_follow "https://target.example.com/login" -H "Accept: text/html"
Out-of-scope requests are blocked and logged to logs/scope-blocks.log.
Kill Switches¶
Every test skill enforces hard limits via the shared boilerplate:
| Limit | Default | Override |
|---|---|---|
| Execution timeout | 45 minutes | SKILL_TIMEOUT env var (60 min for test-injection) |
| Request count | 500 per skill | MAX_REQUESTS env var |
| Request warning | At 400 requests | -- |
| Rate limit (429) | 3 consecutive = stop | Logged via log_event() |
Functions check_timeout() and count_request() are called before every request. When limits are hit, the skill saves progress and exits gracefully.