The global pre-push hook, the /sh-security-review prompt, and finding.schema.json previously lived only in ~/.config/git and ~/.claude (untracked) — unreproducible. Source them here: add hooks/pre-push, rewrite install-hooks.sh with a --global mode (lays down both hooks, sets core.hooksPath, links skill+schema into ~/.claude) and a per-repo mode. Align pre-commit with pre-push (honor skip marker + suppressions). Add semgrep p/javascript so the scanners cover the org's Node/.NET repos.
93 lines
6.1 KiB
Markdown
93 lines
6.1 KiB
Markdown
---
|
|
name: sh-security-review
|
|
description: High-recall agentic security review with anti-complacency structure. Opus fans out N narrow fresh-context detectors over the target, a separate fresh-context verifier demands proof-of-exploit or downgrades to unverified, then findings are emitted in the structured schema with a block decision. Returns severity-ranked findings each carrying a concrete proof.
|
|
---
|
|
|
|
# Sea Haven Security Review (detector fan-out + proof-or-kill verifier)
|
|
|
|
A high-recall security review built to resist reviewer complacency. Instead of one model judging the
|
|
whole surface (that's `sh-build-review`), this fans out **N narrow detectors, each fresh context and
|
|
adversarial**, then a **separate verifier** with the opposing incentive demands a concrete
|
|
proof-of-exploit for every candidate or downgrades it to `unverified`. Output is the structured
|
|
finding schema (`~/.claude/security-review/finding.schema.json`) plus a block decision.
|
|
|
|
This is the interactive (Path A) entry point and runs under the Max subscription. The same prompts and
|
|
schema are reused by the automated `review.sh` (Path B) later. See memory `project-security-review-agent`.
|
|
|
|
## When to Use
|
|
- Security review of a branch, working tree, file, or whole repo
|
|
- Before pushing payments/auth/IaC/input-handling changes
|
|
- As the high-recall pass; complements `/security-review`, `/code-review ultra`, and `sh-build-review`
|
|
|
|
## Arguments
|
|
- Optional target: a path, file, branch, or diff. Default: the current working tree / branch diff vs main.
|
|
- Optional `--scope <dirs>`: restrict the scan (e.g. `src/ infra/ web/`).
|
|
|
|
## Mechanism (Opus runs these)
|
|
|
|
Opus is the main loop. It scopes the target, runs the detector fan-out and verifier as subagents
|
|
(each with **fresh context** so no "we already passed 10 files" approval prior accumulates), then
|
|
applies the gate rule and reports. Opus does NOT soften the gate; the block condition is mechanical.
|
|
|
|
### 1. Scope
|
|
Identify the files in scope (respect `--scope`; never scan an answer key or `.git`). Note the languages
|
|
present (Python/Lambda, .NET, React/JS, SAM/CDK IaC) so detectors apply the right checklist.
|
|
|
|
### 2. Detector fan-out (parallel, fresh context, closed checklist, adversarial)
|
|
Spawn these detectors as **separate parallel subagents** (`subagent_type: general-purpose`). Each gets
|
|
ONLY its category, the schema, and the adversarial framing. Each must, per checklist item, either cite a
|
|
specific safe line OR file a finding — no open "looks fine" judgment.
|
|
|
|
Detectors:
|
|
- **injection** — SQL/command/template injection, unsafe deserialization, SSRF, path/file traversal, XXE
|
|
- **authz** — broken object-level auth/IDOR, missing access checks, missing webhook/Slack signature verification, auth bypass
|
|
- **secrets-crypto** — hardcoded secrets/keys, weak/again crypto (MD5/SHA1/unsalted), sensitive data in logs/errors/responses, wrong SSM-vs-Secrets-Manager
|
|
- **iac-iam** — wildcard IAM actions/resources, public buckets/endpoints, open security-group ingress (0.0.0.0/0), missing encryption, over-broad trust policies
|
|
- **web-client** — XSS (incl. dangerouslySetInnerHTML), CSRF, open redirect, client-side secret exposure
|
|
- **logic** — broken multi-step invariants, race conditions, missing tenant isolation, auth-state confusion
|
|
|
|
Detector prompt template (fill `{CATEGORY}`, `{CHECKLIST}`, `{SCOPE}`):
|
|
```
|
|
You are a hostile {CATEGORY} security auditor for Sea Haven. Assume this code is hostile and the author
|
|
missed something. Audit ONLY {CATEGORY} issues in: {SCOPE}. Read the actual files.
|
|
For each checklist item, either name a specific line that is safe, OR file a finding. Do not hand-wave.
|
|
Checklist: {CHECKLIST}
|
|
Return a JSON array of findings, each: {id, title, claimed_severity (critical|high|medium|low|info),
|
|
cwe (CWE-####), file, line, category:"{CATEGORY}", data_flow (numbered source->sink trace),
|
|
proof:{input, outcome, test|null}, recommendation}. If none, return []. No prose outside the JSON.
|
|
```
|
|
|
|
### 3. Verifier (separate subagent, fresh context, proof-or-kill)
|
|
Spawn one or more **verifier** subagents with the OPPOSING incentive. The verifier did not find these and
|
|
is rewarded for killing weak claims. For each candidate it demands a concrete, plausible proof.
|
|
```
|
|
You are a skeptical exploitation verifier. You did NOT find these; your job is to REFUTE weak claims.
|
|
For each candidate finding, decide: is there a concrete, plausible proof-of-exploit (a specific malicious
|
|
input and the specific bad outcome, consistent with the code)?
|
|
- If yes: status="confirmed", keep severity = claimed_severity, tighten the proof.
|
|
- If no / speculative / not reachable: status="unverified" and severity="unverified". Default to unverified
|
|
when uncertain. A confident assertion without a demonstrable input is NOT proof.
|
|
Return the findings array with status, severity, and the verified proof. No prose outside the JSON.
|
|
```
|
|
|
|
### 4. Merge + gate (mechanical, Opus does not soften)
|
|
- Dedup by (file, cwe, nearby line); keep the highest accepted severity.
|
|
- `summary.confirmed_critical` / `confirmed_high` = counts of status=confirmed at that severity.
|
|
- `summary.block = true` if any unsuppressed confirmed critical/high exists.
|
|
- A finding may be suppressed ONLY with a written `suppression_justification`, which is surfaced in the report.
|
|
No silent dismissal: a critical/high with no proof becomes `unverified` (still listed), never deleted.
|
|
|
|
### 5. Report
|
|
Emit the schema JSON, then a human summary: BLOCK/PASS, confirmed findings highest-severity-first, each
|
|
with file:line, the numbered data-flow trace, and the proof. List unverified and suppressed separately so
|
|
nothing is silently dropped. The reader reviews proofs, not raw code.
|
|
|
|
## Relationship to existing tooling
|
|
- `sh-build-review` — single deep Fable pass over a change surface (depth, one reasoner).
|
|
- `sh-security-review` — high-recall fan-out + proof-or-kill verifier (breadth + anti-complacency).
|
|
- IAM/policy and Lambda-signature changes still require the mandatory cross-family review per global instructions; this does not replace it.
|
|
|
|
## Output
|
|
- Structured findings (schema) + block decision
|
|
- Confirmed findings with proofs, unverified and suppressed listed separately
|
|
- HARD STOP / BLOCK surfaced when `summary.block` is true
|