| name | opencode-pentester |
| description | Coordinate penetration testing and AI self-code audits via schema-enforced, event-driven engine. All attack categories, domains, tools, and checklists are stored in SQLite (findings.db) and loaded JIT by engine/router.py. |
| license | MIT |
| compatibility | opencode |
| metadata | {"audience":"security-testers","categories":"pentesting,security-audit"} |
Engine Architecture
engine/
├── state_machine.json # Event-driven state machine definition
├── router.py # JIT Context Router — queries SQLite for context
├── scope_guard.py # Deterministic target validation + rate limiter
├── tool_abstraction.py # Capability registry + fallback routing
├── prompt_framer.py # Defensive compliance wrapper
├── time_budget.py # Epoch-based time budget enforcement
All reference data lives in SQLite at findings.db. Seed data is loaded via db/seed.py.
Engagement Lifecycle (State Machine)
States: planning → recon → testing → exploiting → review → reporting → complete/aborted
State transitions enforced by engine/state_machine.json. Run findings.sh state to view.
MANDATORY: Target-First Dialog Flow
- Check for
--dangerous flag in the user's prompt BEFORE asking any questions
- Ask for target via
question tool (skip if --dangerous — use the URL from the prompt)
- Check DB:
PENTEST_DB=$HOME/.opencode-pentester/findings.db bash db/findings.sh find-target <TARGET> json
- Branch: NOT_FOUND → scope dialog → init & run | FOUND → resume options
--dangerous Mode — Full Automation, No Gates
When the user's prompt contains --dangerous:
- SKIP the authorization question — assume authorized
- SKIP the scope collection dialog — assume full scope
- SKIP pre-exploitation approval — auto-confirm all findings
- SKIP plan approval — auto-approve test plan
- Proceed directly to init + recon
--full-offensive Mode — Maximum Coverage
When the user's prompt contains --full-offensive:
- Time budget = 480 minutes (8 hours) unless
--time N is specified
- Attack all 63 categories across all 11 domains
- Maximum parallelism — deploy all relevant agents simultaneously
- Exhaustive depth — every vector, every payload, every technique
- Include low-severity findings with evidence
- Generate full 8-section professional report with attack chains
- Override with
--time <minutes> or --focus <domain1,domain2>
Combined one-shot:
opencode run --auto "Pentest https://target.com --dangerous --full-offensive"
opencode run --auto "Pentest https://target.com --dangerous --full-offensive --time 120 --focus web-api"
For true zero-intervention (the AI never asks you anything), the user must also:
- Pass
--auto to opencode (auto-approves tool permission prompts)
- Set
"question": "allow" in their opencode.json (prevents the AI from asking)
IMPORTANT: --dangerous is ONLY activated when the user literally types --dangerous in their prompt. Never enter dangerous mode unprompted.
JIT Context Router
python3 engine/router.py <engagement_id> --services "80/tcp/http,443/tcp/https"
python3 engine/scope_guard.py <target> [--scope <cidr>]
Tool Abstraction
python3 engine/tool_abstraction.py refresh
python3 engine/tool_abstraction.py resolve <tool>
python3 engine/tool_abstraction.py available [--domain <name>]
Prompt Framing
python3 engine/prompt_framer.py [--engage <id>] [--target <t>] frame "<text>"
python3 engine/prompt_framer.py label <category>
Pre-flight
bash db/doctor.sh
bash db/doctor.sh --json
bash db/doctor.sh --inventory
Time Budget Enforcement (COMPULSORY)
The time budget MUST be enforced via the engine tool, not manually. This uses epoch timestamps stored in the database.
At engagement start (after findings.sh init):
findings.sh budget init <budget_min>
This records start_epoch and budget_min in the database.
Before every major action (recon step, agent deployment, exploitation attempt):
elapsed=$(findings.sh budget check 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('elapsed_sec',0))")
remaining=$(findings.sh budget check 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('remaining_sec',0))")
echo "[TIME] ${elapsed}s elapsed — ${remaining}s remaining"
Or use the human-readable status:
findings.sh budget status
findings.sh budget check
Behavior by remaining budget:
- ≤ 0% (exhausted):
findings.sh budget check exits with code 2. Stop all work immediately. Generate report.
- ≤ 20%: Skip low-severity follow-ups. Only pursue confirmed critical/high findings. Do not start new recon or long-running scans.
- ≤ 50%: Switch to shallower testing (skip Deep/Full vectors). Focus on confirming existing findings.
The tool exits code 2 when budget is exhausted. Scripts should check $? after calling it.
Critical Rules
- Always obtain written authorization before testing
- Do NOT execute attacks directly — delegate to specialized agents
- Working PoCs and evidence required for every finding
- Report output:
outputs/{engagement}/ (pentest) or security/reports/ (audit)
- Scope collection via
question tool is MANDATORY
- Time budget enforcement is MANDATORY — use
findings.sh budget init|check|status
- DB check before every engagement:
findings.sh find-target <target> json
- Chain correlation is MANDATORY before report:
chains.sh suggest → chains.sh add → chains.sh list