forked from bchanot/claude
feat(agents): security-auditor SAST gate + onboard/audit-delta grafts (verify-loops lot 3)
agents/security-auditor.md: fresh read-only-on-code SAST gate. Pinned rulesets p/security-audit + p/secrets + p/owasp-top-ten (owasp REQUIRED — measured: the 2-ruleset baseline misses SQLi + path-traversal entirely on realistic Flask code), never --config auto, never auto login (BDR-048). Severity map: secrets ERROR → CRITICAL, other ERROR → HIGH (block), WARNING/INFO → reported. gate mode (diff, no Write) vs audit mode (Write only to REPORT, rule-locked). DEGRADED (semgrep absent) still runs the checklist and still blocks — never a vacuous pass (LRN-048). Anti-gaming: a new un-gated nosemgrep suppression is BLOCKING. PROOF mandatory, mute auditor never a PASS, blind (no iteration history), blocks HIGH/CRITICAL only (LRN-047). Grafts: onboard STEP 6 L3a dispatches it in audit mode (report .onboard-audit/semgrep.md) in BOTH gstack branches — complement to cso (cso is a gstack submodule, unmodifiable); synthesis picks it up via the existing .onboard-audit/ sweep. audit-delta security axis runs the SAST pass first, folds findings into the existing gate/fix/re-verify flow. lib/tests/security-auditor.test.sh: 28 structure locks green, shellcheck clean. Behavioral dogfood (fresh agents on a planted fixture): BLOCK(9) on the vuln commit (2 secrets→CRITICAL, semgrep+checklist complementarity — checklist caught the 6 semgrep missed off-context); BLOCK(1) on a new nosemgrep suppression (understood semgrep's 0 was the mask); DEGRADED → BLOCK(7) on grep-detectable secrets with semgrep hidden. FP measured on real repos (faunosteo, game): owasp adds only hygiene findings, contained by diff-scoping. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XpphkdTosUzokBDNG7PToS
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ff13abfda5
commit
2b297bd44a
@@ -221,12 +221,21 @@ Then offer to capitalize (per CLAUDE.md): recurring finding patterns →
|
||||
|
||||
## Axis specs (subagent prompts)
|
||||
|
||||
- **security** — scoped to the delta: hardcoded secrets/tokens/keys (also
|
||||
in comments), injection (SQL/XSS/command — string concat into
|
||||
queries/shells), authN/authZ gaps on new endpoints, fail-open error
|
||||
paths, secrets/PII in logs, new dependencies in lockfiles (name them +
|
||||
known CVEs), unguarded destructive shell (`rm -rf` with unquoted or
|
||||
un-`:?`-guarded vars).
|
||||
- **security** — FIRST run the semgrep SAST pass, THEN the reasoned checks
|
||||
below on the same delta (the SAST is a deterministic floor, the reasoned
|
||||
pass covers what grep/rules miss):
|
||||
```
|
||||
Agent(subagent_type="security-auditor", description="audit-delta security — semgrep SAST",
|
||||
prompt="MODE: audit\nSCOPE: <delta file list>\nREPORT: .claude/audits/.audit-delta-semgrep.md\nFollow agents/security-auditor.md exactly. Pinned rulesets, no login. Write ONLY to REPORT. End with REPORT_WRITTEN: <path>.")
|
||||
```
|
||||
Fold its BLOCKING (CRITICAL/HIGH) + REPORTED findings into this axis'
|
||||
finding list before the 3c gate. semgrep ABSENT → DEGRADED (checklist
|
||||
only) is surfaced, not a blocker. Reasoned checks (also scoped to the
|
||||
delta): hardcoded secrets/tokens/keys (also in comments), injection
|
||||
(SQL/XSS/command — string concat into queries/shells), authN/authZ gaps
|
||||
on new endpoints, fail-open error paths, secrets/PII in logs, new
|
||||
dependencies in lockfiles (name them + known CVEs), unguarded destructive
|
||||
shell (`rm -rf` with unquoted or un-`:?`-guarded vars).
|
||||
- **errors** — bugs in changed code: logic errors, off-by-one, unhandled
|
||||
edge cases (empty/null/unicode/concurrent), race conditions, swallowed
|
||||
errors, resource leaks (missing trap/close/finally). Improvements only
|
||||
|
||||
Reference in New Issue
Block a user