Scenario-first whitebox security vulnerability research using the OpenHack methodology (Hadrian Security). 12 OWASP 2025-aligned expert families, recon → route → scenario → triage pipeline. Use for deep source-code audit on a target repo — not for quick YAMTAM rule checks (use strix-scan.sh for that).
Scenario-first whitebox security vulnerability research using the OpenHack methodology (Hadrian Security). 12 OWASP 2025-aligned expert families, recon → route → scenario → triage pipeline. Use for deep source-code audit on a target repo — not for quick YAMTAM rule checks (use strix-scan.sh for that).
license
MIT (methodology adapted from hadriansecurity/openhack)
source
https://github.com/hadriansecurity/openhack
OpenHack Security Review
Scenario-first, checkpointed vulnerability research designed to run inside LLM coding harnesses (Claude Code, Codex, Cursor).
Not a scanner. Does not look for pattern matches. Instead: discovers surfaces → routes to experts → proves/disproves hypotheses → triages findings.
When to Use This vs strix-scan
Situation
Use
Quick rule compliance check
strix-scan.sh (L1–L5)
Full vulnerability research on a codebase
openhack-security-review
Before a production release of a security-sensitive system
Both
Auditing a third-party repo
openhack-security-review
CI gate on every commit
strix-scan.sh only
Trigger phrases: "deep security audit", "whitebox pentest", "vuln research", "OWASP scan", "find vulns in this repo", "security review before launch"
Externally reachable endpoints from framework config
Recon prompt template:
You are performing recon on a codebase for security review.
Target: <path>
Language/framework: <detected>
For each category below, list every discovered surface with:
- file:line reference
- category (route/input/sink/auth-boundary/exposure)
- brief description of what it does and why it's security-relevant
Categories: routes, inputs, sinks, auth-boundaries, exposures
Output as JSONL, one item per line.
Group related surfaces into routing units (one unit = one review context).
Rules:
Same controller/handler → same unit
Related sink + its input sources → same unit
Max 5 surfaces per unit (keeps expert context focused)
Each routing unit gets assigned to 1–3 expert families.
Router prompt output format:
{"routing_unit_id":"RU-001","surfaces":["routes:POST /api/user","sinks:db.query(sql)"],"assigned_experts":["injection","broken-access-control"],"proof_question":"Can attacker-controlled input reach the SQL sink without sanitization?"}
Phase 2 — The 12 Expert Families
Each expert has a root-cause family, OWASP/CWE ID, and specific techniques.
Expert 01 — Broken Access Control (A01:2025)
Horizontal/vertical privilege escalation
BOLA: object references not verified against authenticated user
A finding is only valid when ALL of the following are demonstrated:
1. REACHABLE ENTRYPOINT — attacker can reach this code path
2. ATTACKER-CONTROLLED INPUT — the dangerous value is attacker-supplied
(including stored/second-order flows)
3. SENSITIVE SINK — the value reaches a dangerous operation
4. MISSING/WRONG GUARD — no sanitization, or guard is bypassable
in the specific context
5. CONCRETE IMPACT — what can attacker actually do?
Without all 5, verdict = rejected or needs_context.
Evidence format per finding:
{"title":"SQL injection via unsanitized user_id parameter","severity":"critical","expert":"injection","evidence":[{"file":"src/api/users.ts","line":42,"snippet":"db.query(`SELECT * FROM users WHERE id=${req.params.id}`)"},{"file":"src/routes/users.ts","line":15,"snippet":"router.get('/users/:id', getUser)"}],"attacker_role":"unauthenticated","preconditions":"None — endpoint is public","attack_chain":"GET /users/1' OR 1=1-- → SQL bypasses filter → full table dump","impact":"Full database read, potential authentication bypass","recommended_fix":"Use parameterized query: db.query('SELECT * FROM users WHERE id = ?', [req.params.id])"}
Phase 3 — Triage
Independent review of each finding candidate:
Decision
Meaning
accepted
Evidence complete, impact confirmed, report it
downgraded
Real but severity lower than claimed
duplicate
Same vuln as existing finding
rejected
Evidence incomplete, proof obligations not met
needs_context
Requires more code context to decide
Only accepted and downgraded become final findings.
❌ Finding without file:line evidence = REJECTED
❌ "Potential SQL injection" without confirming attacker can reach it = REJECTED
❌ Scanner hit (semgrep match) alone = finding CANDIDATE, not confirmed finding
❌ "This function is dangerous" without tracing input to dangerous call = REJECTED
❌ CRITICAL severity without documenting attacker role and attack chain = DOWNGRADED
❌ Reporting findings based on code patterns that exist but are unreachable = REJECTED
See Also
core/scripts/strix-scan.sh — fast L1-L5 rule check
core/rules/api-security-gate.md — OWASP API Top 10