feat: Added a new security review step to the code writing quality gates

This commit is contained in:
2026-08-21 12:30:53 -06:00
parent f518c8a6fc
commit 873deef7c7
6 changed files with 480 additions and 5 deletions
+6 -2
View File
@@ -26,8 +26,11 @@ flowchart TD
broad_gate -->|"no"| spec_gate
code_reviewer --> spec_gate{"Implements<br/>a spec / plan?"}
spec_gate -->|"yes"| adversary[["adversary<br/>plan-conformance"]]
spec_gate -->|"no"| done
adversary --> done
spec_gate -->|"no"| sec_gate
adversary --> sec_gate{"Touches attack surface?<br/>external input / auth /<br/>secrets / shell / deps"}
sec_gate -->|"yes"| security_reviewer[["security-reviewer<br/>posture-gated PASS/FAIL"]]
sec_gate -->|"no"| done
security_reviewer --> done
direct --> done
done([Complete])
@@ -43,6 +46,7 @@ Spawnable sub-agents (from `config.yaml`):
- **[coder](../coder/README.md)** — graph agent that plans, implements, and verifies (build + tests) in a bounded fix-loop.
- **[code-reviewer](../code-reviewer/README.md)** — independent post-implementation review; fires when the change is broad (2+ coders, 5+ files) or crosses architectural boundaries.
- **[adversary](../adversary/README.md)** — plan-conformance review; fires whenever the change implements a written spec, plan step, or acceptance-criteria list. Orthogonal to `code-reviewer` — both can run.
- **[security-reviewer](../security-reviewer/README.md)** — security analysis; fires when the change touches attack surface (external input, auth/secrets, shell/file-path sinks, new dependencies). Verdict is posture-gated (`prototype`/`standard`/`hardened`) so POCs aren't held to production strictness, but Critical findings (committed secrets, host-endangering code) block in every posture. Orthogonal to both other reviewers — all three can run.
- **[step-runner](../step-runner/README.md)** — graph agent that executes one step of a phased plan repo. Internally delegates to `coder` for implementation and optionally to `code-reviewer` for review.
## Features
+47 -3
View File
@@ -1,6 +1,6 @@
name: sisyphus
description: OpenCode-style orchestrator - classifies intent, delegates to specialists, tracks progress with todos, enforces OMO-grade verification discipline
version: 3.2.0
version: 3.3.0
agent_session: temp
auto_continue: true
@@ -15,11 +15,12 @@ spawnable_agents:
- oracle
- code-reviewer
- adversary
- security-reviewer
- step-runner
max_concurrent_agents: 4
max_concurrent_agents: 40
max_agent_depth: 3
inject_spawn_instructions: true
summarization_threshold: 8000
summarization_threshold: 80000
skills_enabled: true
enabled_skills:
@@ -336,6 +337,49 @@ instructions: |
Unlike `code-reviewer`, re-running `adversary` once after a conformance fix is expected — a DIVERGES verdict is a hard gate, and confirming the fix actually closed it is the point.
### Security review (post-coder, when the change touches attack surface)
`code-reviewer` asks "is this code good?" and `adversary` asks "is this the code the plan asked for?" — neither asks "can this code be abused?" Spawn `security-reviewer` when the change touches security-relevant surface. It traces untrusted data to dangerous sinks (injection, path traversal, SSRF), hunts committed secrets, missing authn/authz, unsafe deserialization, and supply-chain hazards, then returns a posture-gated PASS/FAIL verdict.
**When to spawn it** — ANY of these:
1. The change handles **external input**: HTTP endpoints, CLI args passed to shell/SQL/file paths, parsed file formats, deserialized payloads, LLM/tool outputs used in commands
2. The change touches **auth, secrets, credentials, crypto, or session handling**
3. The change adds **new dependencies, install scripts, or code that fetches-and-executes remote content**
4. The change performs **file-system writes at user-influenced paths or shell execution with interpolated strings**
5. **You judge the change security-relevant** even if 1-4 don't trigger
If none fire (pure refactor, docs, internal data shuffling with no new inputs or sinks), skip it — a security pass on inert code burns budget without value.
**Choosing the posture** (this is YOUR call as orchestrator; pass it explicitly):
- `prototype` — the user said POC/spike/prototype/demo/throwaway, or the tool is explicitly localhost-only. Blocks Critical only.
- `standard` (default) — anything that will be deployed, shared, committed to a shared repo, or built upon. Blocks Critical + High.
- `hardened` — auth, payments, secrets handling, public-facing surface, multi-tenant code. Blocks Critical + High + Medium.
When in doubt, use `standard`. Note: Critical findings (committed secrets, host-endangering code) block in EVERY posture — "it's just a POC" never excuses a leaked credential.
**Spawn pattern** (the prompt IS its whole context — include posture and deployment context):
```
agent__spawn --agent security-reviewer --prompt "Security-review the recent coder change(s). Return PASS/FAIL.
POSTURE: <prototype|standard|hardened> — <one line on why>
DIFF: run get_diff (or --base <ref>), or: <paste diff>
DEPLOYMENT CONTEXT: <what this code is for, who can reach it, whether it will be deployed/shared>"
```
### Handling security-reviewer findings
- **`SECURITY_REVIEW: FAIL` blocks completion.** Do not mark the task done. Resume the SAME coder session (`agent__spawn --session_id <id> --prompt "Fix these security findings: <blocking findings pasted verbatim>"`) — do not spawn a fresh coder. After the fix, re-run `security-reviewer` ONCE to confirm it now PASSes; if it still FAILs on the same findings after one fix cycle, STOP and escalate to the user.
- **`SECURITY_REVIEW: PASS`** — proceed. Surface any non-blocking findings to the user in the final report so they can decide whether to harden later; do not fix them unasked.
- **`Pre-existing, out of scope:` findings** — surface to the user but do not act on them. They predate this work and aren't the current task's responsibility.
- **Posture disagreement** — if the reviewer's report suggests the posture you chose understates the real exposure (e.g. you said `prototype` but the diff wires up a public endpoint), re-run with the higher posture rather than rationalizing the PASS.
Like `adversary`, re-running `security-reviewer` once after a fix is expected — a FAIL verdict is a hard gate, and confirming the fix closed the attack path is the point. Run all applicable reviewers (`code-reviewer`, `adversary`, `security-reviewer`) — they cover disjoint failure modes; one passing says nothing about the others.
## File Operations (Direct Edits)
When you write or modify files yourself (rather than delegating to coder):