baldart 5.8.0 → 5.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +1 -1
- package/VERSION +1 -1
- package/framework/.claude/agents/CHANGELOG.md +18 -0
- package/framework/.claude/agents/security-reviewer.md +53 -1
- package/framework/agents/index.md +2 -1
- package/framework/agents/security-review-protocol.md +233 -0
- package/framework/agents/security.md +50 -46
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ All notable changes to BALDART will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [5.9.0] - 2026-07-06
|
|
9
|
+
|
|
10
|
+
**`security-reviewer` upgraded to the 2026 AppSec state of the art — benchmarked against Codex `codex-security` + Claude Code `security-guidance`, imported as a single-sourced protocol module.**
|
|
11
|
+
The `security-reviewer` was a high-quality *monolithic* agent (senior persona, dual review/apply, pooled YAML, generic Challenge/CoVe via `review-protocol.md`) but stuck at a single-pass "read → list findings by severity" model. A benchmark against two real corpora — Codex's phased `codex-security` workbench (threat-model → discovery → validation → attack-path → severity, coverage ledgers, instance-preserving proof) and Claude Code's `security-guidance` agentic reviewer (adversarial self-refute, attacker≠victim, modern high-miss patterns) — found BALDART at ~60% of current best practice. This wave closes the gap **without a monolithic rewrite**, following the agent-spine 3-layer model.
|
|
12
|
+
|
|
13
|
+
- **New protocol module [`framework/agents/security-review-protocol.md`](framework/agents/security-review-protocol.md)** — the AppSec verification engine, the security twin of `review-protocol.md`. `SECTION=` dispatch: `boundary-gate` (read `SECURITY.md` + classify `product_surface`/`source_trust`/`boundary_crossed` before confirming), `threat-model` (repository-scoped, never diff-biased), `discovery-lens` (the modern **high-miss** taxonomy: fail-open state drift, allowlist semantic escape, control regression, gate/action field mismatch, parser/validator differential, sensitive-to-observability, CI/CD trust, IaC omitted arg, over-broad grant, stale identity mapping, security-registry fanout, resource-bound placement), `proof-tuples` (class-specific validation tuples + confidence anchored to validation **method** not bug class + instance-preserving), `attack-path` (structured facts → **mechanical** severity), `adversarial-refute` (SURVIVES-unless-refuted, the **attacker≠victim** privilege-boundary test first, precondition-vs-counterevidence discipline, diff newly-introduced-only), `coverage-ledger` (surface dispositions so a clean verdict is honest). It **EXTENDS** `review-protocol.md`'s generic passes, never duplicates them — no dual-SSOT.
|
|
14
|
+
- **`security-reviewer` agent (v1.0.0)** — gains a versioned frontmatter + a "Security Review Passes (BINDING)" block that cites the module with 1-line binding statements (agent-spine: core inline + module on demand). Mode A pooled YAML schema gains `vuln_class`, `cwe: [CWE-###]`, `validation_method`, and a structured `attack_path` block; the summary header carries a compact `coverage:` block. New **secret-redaction** BINDING (report a leaked credential as first 2–4 chars + `****`, never the live value — a review artifact reproducing a secret is itself a leak).
|
|
15
|
+
- **`framework/agents/security.md`** — the consumer-facing security template modernized from **OWASP Top 10:2017 → 2021** (XXE folded into Security Misconfiguration, insecure deserialization into Software & Data Integrity Failures, XSS into Injection; new A04 Insecure Design + A10 SSRF), with a 2025-draft note.
|
|
16
|
+
- Routing wired in `agents/index.md` (security routing rule + Modules list). README security-reviewer inventory line updated.
|
|
17
|
+
- **Codex parity: portable** — the module is markdown read at runtime by both runtimes; the agent-body edits transpile to `.codex/agents/security-reviewer.toml` automatically. **No new `baldart.config.yml` key** → the schema-change propagation rule does NOT apply.
|
|
18
|
+
|
|
8
19
|
## [5.8.0] - 2026-07-06
|
|
9
20
|
|
|
10
21
|
**Suggested launch plan at the end of `/prd` — waves with a NAME, persisted on the epic card.**
|
package/README.md
CHANGED
|
@@ -92,7 +92,7 @@ No additional activation steps needed — once installed, Claude Code (and Codex
|
|
|
92
92
|
1. **codebase-architect**: MANDATORY before planning/implementation - understands codebase structure
|
|
93
93
|
2. **coder**: Writes production code with build/test/lint verification + Post-Approval Complexity Gate
|
|
94
94
|
3. **code-reviewer**: Reviews for bugs, security, quality, maintainability — confidence-based filtering + Findings Schema
|
|
95
|
-
4. **security-reviewer**: Dedicated AppSec auditor for auth/secrets/multi-tenant/infra
|
|
95
|
+
4. **security-reviewer**: Dedicated AppSec auditor for auth/secrets/multi-tenant/infra — boundary-gate → repo-scoped threat-model → modern high-miss discovery-lens → class proof-tuples → structured attack-path → adversarial-refute (`security-review-protocol.md`)
|
|
96
96
|
5. **doc-reviewer**: Audits and writes documentation, SSOT sync, doc debt tracking, design-system drift detection
|
|
97
97
|
6. **wiki-curator**: Maintains the derived LLM wiki overlay (`docs/wiki/`) — synthesis candidates, anchor + frontmatter validation
|
|
98
98
|
7. **prd**: Creates PRDs, implementation plans, and backlog cards with autonomous tech decisions
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.
|
|
1
|
+
5.9.0
|
|
@@ -7,6 +7,24 @@ per-item agent merge, the doctor probes, and the discovery hooks — like
|
|
|
7
7
|
|
|
8
8
|
Formato: [Keep a Changelog](https://keepachangelog.com/) · per-agent SemVer.
|
|
9
9
|
|
|
10
|
+
## [security-reviewer v1.0.0] — 2026-07-06 (framework v5.9.0 — AppSec state-of-the-art wave)
|
|
11
|
+
|
|
12
|
+
- **First versioned entry.** Benchmarked against Codex `codex-security` (phased
|
|
13
|
+
workbench) + Claude Code `security-guidance` (agentic self-refute); imported the
|
|
14
|
+
gap as a single-sourced protocol module rather than a monolithic rewrite.
|
|
15
|
+
- **New "Security Review Passes (BINDING)" block** — cites the new
|
|
16
|
+
`agents/security-review-protocol.md` with 1-line binding statements per section
|
|
17
|
+
(boundary-gate, threat-model, discovery-lens, proof-tuples, attack-path,
|
|
18
|
+
adversarial-refute, coverage-ledger). Agent-spine 3-layer: core inline + module
|
|
19
|
+
on demand. EXTENDS `review-protocol.md`, never duplicates it.
|
|
20
|
+
- **Mode A pooled YAML schema extended**: `vuln_class`, `cwe: [CWE-###]`,
|
|
21
|
+
`validation_method`, structured `attack_path` block; summary header gains a
|
|
22
|
+
compact `coverage:` block. Other reviewers ignore the security-only fields.
|
|
23
|
+
- **Secret-redaction BINDING** added to Behavior Rules — a leaked credential is
|
|
24
|
+
reported as first 2–4 chars + `****`, never the live value.
|
|
25
|
+
- Codex parity: agent body transpiles to `.codex/agents/security-reviewer.toml`
|
|
26
|
+
automatically; the module is portable markdown. No new config key.
|
|
27
|
+
|
|
10
28
|
## [prd-card-writer v1.2.0] — 2026-07-04 (framework v5.6.0 — FEAT-0068 post-mortem)
|
|
11
29
|
|
|
12
30
|
- **Epic AC rules**: mai count di figli hardcodato ("le 6 sub-card"); AC con
|
|
@@ -4,6 +4,7 @@ description: "Use this agent when code needs a security review, when reviewing P
|
|
|
4
4
|
model: sonnet
|
|
5
5
|
color: red
|
|
6
6
|
memory: project
|
|
7
|
+
version: 1.0.0
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
> **YOLO MODE**: All agents spawned via the Task tool MUST use `mode: "bypassPermissions"`. No exceptions.
|
|
@@ -73,6 +74,7 @@ file you EXPECT to match is a binary-mode trap, not evidence: re-run with `rg` (
|
|
|
73
74
|
- NEVER hand-wave or give shallow "looks good" feedback.
|
|
74
75
|
- NEVER approve insecure code because it is "probably internal".
|
|
75
76
|
- NEVER recommend storing secrets in code, env files committed to git, client-side code, or logs.
|
|
77
|
+
- **Secret redaction (BINDING).** When you report a leaked/hardcoded credential, NEVER write its full value — redact to the first 2–4 characters + `****`. Cite the `file:line` (the canonical source location), state what the credential grants and whether it is prod vs test, and recommend rotation if it is live. A review artifact that reproduces a live secret is itself a leak.
|
|
76
78
|
- NEVER suggest disabling security controls for convenience unless explicitly discussing a temporary local-only dev workaround, clearly labeled as unsafe.
|
|
77
79
|
|
|
78
80
|
## Threat-Modeling Mindset
|
|
@@ -88,6 +90,43 @@ For every review, actively reason about:
|
|
|
88
90
|
- Insider threat / compromised service misuse
|
|
89
91
|
- Multi-tenant isolation boundaries (critical for any multi-customer platform)
|
|
90
92
|
|
|
93
|
+
## Security Review Passes (BINDING — full procedure in the protocol module)
|
|
94
|
+
|
|
95
|
+
These extend `review-protocol.md`'s generic passes (Challenge / Simulation /
|
|
96
|
+
CoVe / risk-scoring) with the AppSec specifics. Keep the 1-line binding here;
|
|
97
|
+
Read the matching section of `agents/security-review-protocol.md SECTION=<name>`
|
|
98
|
+
for the procedure. Order: boundary-gate (once) → threat-model → discovery-lens →
|
|
99
|
+
per candidate proof-tuples → attack-path → adversarial-refute → mechanical
|
|
100
|
+
severity → coverage-ledger.
|
|
101
|
+
|
|
102
|
+
- **BINDING — boundary-gate**: before confirming anything, read `SECURITY.md` /
|
|
103
|
+
deployment notes and classify the surface (`product_surface`, `source_trust`,
|
|
104
|
+
`boundary_crossed`); no boundary crossed → not a finding. `SECTION=boundary-gate`.
|
|
105
|
+
- **BINDING — threat-model**: adopt or generate a REPOSITORY-scoped threat model
|
|
106
|
+
(never diff-biased); it picks your focus paths. `SECTION=threat-model`.
|
|
107
|
+
- **BINDING — discovery-lens**: sweep the modern high-miss patterns (fail-open,
|
|
108
|
+
allowlist-escape, control-regression, gate/action mismatch, parser
|
|
109
|
+
differential, sensitive-to-observability, CI/CD trust, IaC omitted arg,
|
|
110
|
+
over-broad grant, stale identity, registry fanout) beyond the OWASP core.
|
|
111
|
+
`SECTION=discovery-lens`.
|
|
112
|
+
- **BINDING — proof-tuples**: ground every finding in its class-specific tuple
|
|
113
|
+
(authz = path + missing guard + protected object; injection = bytes + sanitizer
|
|
114
|
+
result + sink; SSRF; deserialization; auth/token; XSS); confidence is anchored
|
|
115
|
+
to validation METHOD, not to how scary the bug class sounds; never collapse
|
|
116
|
+
independently exploitable sibling instances. `SECTION=proof-tuples`.
|
|
117
|
+
- **BINDING — attack-path**: write structured attack-path facts (attacker,
|
|
118
|
+
entrypoint, preconditions, dataflow source→sink, outcome, impact×likelihood)
|
|
119
|
+
BEFORE severity, then apply severity mechanically. `SECTION=attack-path`.
|
|
120
|
+
- **BINDING — adversarial-refute**: a finding SURVIVES unless refuted; test the
|
|
121
|
+
privilege boundary FIRST (attacker == victim on own machine → refute); keep
|
|
122
|
+
precondition (narrows likelihood) distinct from counterevidence (kills the
|
|
123
|
+
finding). In diff review, flag only newly-introduced/reachable surface.
|
|
124
|
+
`SECTION=adversarial-refute`.
|
|
125
|
+
- **BINDING — coverage-ledger**: record a disposition for every surface in scope
|
|
126
|
+
(`reported` / `no_issue_found` / `not_applicable` / `needs_follow_up` /
|
|
127
|
+
`deferred`) so a clean verdict is honest and a gap is never silent; zero
|
|
128
|
+
findings on a fully-covered surface is a legitimate outcome. `SECTION=coverage-ledger`.
|
|
129
|
+
|
|
91
130
|
## Review Methodology
|
|
92
131
|
|
|
93
132
|
For each file, code block, PR, or diff you review:
|
|
@@ -129,18 +168,27 @@ determine as `N/A` rather than dropping the finding):
|
|
|
129
168
|
title: <one-line>
|
|
130
169
|
source: security-reviewer
|
|
131
170
|
category: security
|
|
171
|
+
vuln_class: <concrete class, e.g. "Authorization bypass / IDOR" — never a generic "security finding">
|
|
172
|
+
cwe: [<CWE-###>, ...] # e.g. [CWE-22, CWE-434]; [] if none maps cleanly
|
|
132
173
|
target: <one of the orchestrator's TARGET TAG values, or "notes" for informational>
|
|
133
174
|
severity: BLOCKER | HIGH | MEDIUM | LOW
|
|
134
|
-
confidence: 0-100
|
|
175
|
+
confidence: 0-100 # anchored to validation_method (proof-tuples), not to the bug class
|
|
135
176
|
evidence:
|
|
136
177
|
file: <path or "N/A">
|
|
137
178
|
lines: <range or "N/A">
|
|
138
179
|
quote: |
|
|
139
180
|
<exact code snippet, ≤8 lines>
|
|
140
181
|
cove_verified: true | false # true if you verified file/line via Glob/Grep/Read
|
|
182
|
+
validation_method: <poc | test | debugger | interface-repro | static-trace | code-understanding>
|
|
141
183
|
repro_steps: <exploitation scenario — how an attacker reaches and triggers this>
|
|
142
184
|
expected_behavior: <the secure behavior>
|
|
143
185
|
actual_behavior: <the vulnerable behavior present in the code>
|
|
186
|
+
attack_path: # structured facts → severity falls out mechanically
|
|
187
|
+
attacker: <who, trust level, from where>
|
|
188
|
+
entrypoint: <exact reachable entry — route/RPC/CLI/webhook/MCP tool>
|
|
189
|
+
preconditions: <conditions required; "none" if unconditional>
|
|
190
|
+
dataflow: <source → sink, one line>
|
|
191
|
+
outcome: <concrete impact — data read/written, code executed, tenant crossed>
|
|
144
192
|
risk:
|
|
145
193
|
impact: 1-5
|
|
146
194
|
likelihood: 1-5
|
|
@@ -148,6 +196,10 @@ determine as `N/A` rather than dropping the finding):
|
|
|
148
196
|
recommendation: <concrete, minimal, production-ready fix; ≤3 sentences>
|
|
149
197
|
```
|
|
150
198
|
|
|
199
|
+
The `# Security Review Summary` header that follows the YAML list carries a
|
|
200
|
+
compact `coverage:` block (surfaces + dispositions per `SECTION=coverage-ledger`)
|
|
201
|
+
so the orchestrator can tell a clean verdict from an incomplete one.
|
|
202
|
+
|
|
151
203
|
Map your severity labels to the pooled enum: Critical → `BLOCKER`, High → `HIGH`, Medium →
|
|
152
204
|
`MEDIUM`, Low/Informational → `LOW`. Follow the YAML list with a 3–4 line plain-text
|
|
153
205
|
`# Security Review Summary` (scope / overall risk / main attack surfaces / most critical concern) so
|
|
@@ -37,7 +37,7 @@ Route agents to the right module with minimal reading.
|
|
|
37
37
|
- If touching terminology or naming -> read `agents/coding-standards.md`.
|
|
38
38
|
- If touching env vars or scripts -> read `agents/runbook.md` and `agents/env-reference.md`.
|
|
39
39
|
- If touching operational procedures (backup, cleanup, secrets) -> read `docs/operations/` if it exists in your project.
|
|
40
|
-
- If touching security or auth risk -> read `agents/security.md
|
|
40
|
+
- If touching security or auth risk -> read `agents/security.md` (OWASP 2021 posture + secure-defaults). If performing a dedicated AppSec review (the `security-reviewer` agent, `/codexreview` security pass) -> also read `agents/security-review-protocol.md` (the matching `SECTION=` only): boundary-gate → repo-scoped threat-model → high-miss discovery-lens → class proof-tuples → structured attack-path → adversarial-refute (attacker≠victim) → coverage-ledger. It EXTENDS `review-protocol.md` (generic passes), never duplicates it.
|
|
41
41
|
- If touching performance limits or scaling -> read `agents/performance.md`.
|
|
42
42
|
- If touching monitoring/logging -> read `agents/observability.md`.
|
|
43
43
|
- If tuning reasoning depth — setting a skill's `effort:` baseline or honoring an inline `effort=<level>` override -> read `agents/effort-protocol.md`.
|
|
@@ -86,6 +86,7 @@ When adding or updating agents, update REGISTRY.md — not this file.
|
|
|
86
86
|
- `agents/runtime-portability-protocol.md` — Runtime-mechanics binding: the abstract-operation ↔ Claude/Codex map (spawn / permissions / workflow-accel / state-spine / decision-gate / read-write path / adversarial-vs-cross-model), detect-once capability contract; cited by `/new` + `/prd`. The runtime-mechanics twin of `effort-protocol.md` + `return-contract-protocol.md` (since the Codex-parity S4 wave)
|
|
87
87
|
- `agents/agent-operating-protocol.md` — Shared operating procedures for the core agents (injection guard, doc-retrieval consumption, persistent-memory hygiene, tool-budget discipline), `SECTION=` dispatch, read only the matching section; agents keep 1-line binding versions inline (since v5.0.0)
|
|
88
88
|
- `agents/review-protocol.md` — The shared verification engine for reviewers: Challenge + Actionability, Simulation (diff-walk / plan-walk), Chain-of-Verification, quantified risk scoring + absolute severity calibration, specialist-spawn discipline incl. orchestrated-mode `specialist_dispatch` suppression; `SECTION=` dispatch (since v5.0.0)
|
|
89
|
+
- `agents/security-review-protocol.md` — The AppSec verification engine for `security-reviewer`: boundary-gate, repository-scoped threat-model, modern high-miss discovery-lens (fail-open / allowlist-escape / control-regression / gate-action mismatch / parser differential / CI-CD trust / IaC omitted arg / over-broad grant), class-specific proof-tuples (method-anchored confidence, instance-preserving), structured attack-path → mechanical severity, adversarial-refute (attacker≠victim, precondition vs counterevidence), coverage-ledger; `SECTION=` dispatch. EXTENDS `review-protocol.md`, never duplicates it. Portable Claude+Codex (since v5.9.0)
|
|
89
90
|
- `agents/doc-audit-protocol.md` — doc-reviewer's audit-mode procedures (drift validator suite, topological generation, epistemic metadata, SCIP anchors, schema/registry drift, coverage gauges); read ONLY when invoked without card context; `SECTION=` dispatch (since v5.0.0)
|
|
90
91
|
- `agents/research-protocol.md` — Research discipline: `PROFILE=<decision|deep|compare|regulatory>` output contracts (+ `DEPTH=` iterative loop), the research library (`paths.research_dir` — layout, report frontmatter, INDEX, archive-not-delete), the reuse pre-flight (`FULL_REUSE`/`DELTA`/`NEW` + per-category TTLs), and the versioned source matrix with its growth loop (`SOURCE_MATRIX_CANDIDATE`); `SECTION=` dispatch. The research-side sibling of `analysis-profiles.md` (since v5.1.0)
|
|
91
92
|
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Security Review Protocol — the AppSec verification engine
|
|
2
|
+
|
|
3
|
+
**Purpose**: the security-specific passes that turn a generic code review into
|
|
4
|
+
an adversarial AppSec audit — repository-scoped threat modeling, the modern
|
|
5
|
+
high-miss discovery lens, class-specific proof tuples, structured attack-path →
|
|
6
|
+
mechanical severity, adversarial self-refutation (attacker vs victim), and a
|
|
7
|
+
coverage ledger so *"not observed" never reads as "not reviewed"*. Distilled
|
|
8
|
+
from the Codex `codex-security` workbench + the Claude Code `security-guidance`
|
|
9
|
+
agentic reviewer. This module is the **single SSOT** of that methodology.
|
|
10
|
+
|
|
11
|
+
**Relationship to `review-protocol.md`**: that module owns the GENERIC verifier
|
|
12
|
+
passes (Challenge, Actionability, Simulation, Chain-of-Verification, risk
|
|
13
|
+
scoring). This module **extends**, never duplicates them: `adversarial-refute`
|
|
14
|
+
is the security-specialized layer that runs *inside* the generic Challenge pass;
|
|
15
|
+
`proof-tuples` is the security grounding for the generic CoVe pass. On the
|
|
16
|
+
generic passes, `review-protocol.md` wins; on AppSec specifics, this module
|
|
17
|
+
wins.
|
|
18
|
+
|
|
19
|
+
**Consumer**: `security-reviewer` (body citations). Portable as-is across Claude
|
|
20
|
+
Code and Codex (read at runtime by both).
|
|
21
|
+
|
|
22
|
+
## Contract
|
|
23
|
+
|
|
24
|
+
- **Dispatch**: cite `agents/security-review-protocol.md SECTION=<threat-model|discovery-lens|proof-tuples|attack-path|adversarial-refute|coverage-ledger|boundary-gate>`.
|
|
25
|
+
Grep for `### SECTION: <name>` and Read ONLY that section.
|
|
26
|
+
- **Order of passes** (normative): `boundary-gate` (once, at kickoff) →
|
|
27
|
+
`threat-model` (adopt or generate) → discovery under the `discovery-lens` →
|
|
28
|
+
per candidate: `proof-tuples` (validation) → `attack-path` (structured facts)
|
|
29
|
+
→ `adversarial-refute` → mechanical severity (`review-protocol.md
|
|
30
|
+
SECTION=risk-scoring`) → `coverage-ledger` close. The generic Challenge + CoVe
|
|
31
|
+
passes still run; the security passes feed them.
|
|
32
|
+
- **Degrade-safe**: skipping a pass means less rigor, never a malformed report —
|
|
33
|
+
the report/YAML shape stays defined in the agent body.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
### SECTION: boundary-gate
|
|
38
|
+
|
|
39
|
+
Run ONCE before confirming any finding. A vulnerability only exists when an
|
|
40
|
+
attacker crosses a trust boundary of a **shipped/deployed** surface — so
|
|
41
|
+
classify the surface first, or you will flag same-privilege local code as a
|
|
42
|
+
"vuln".
|
|
43
|
+
|
|
44
|
+
1. **Read the repo's own policy FIRST**: `SECURITY.md`, `AGENTS.md` deployment
|
|
45
|
+
notes, package metadata. They define which surfaces are in-scope and what the
|
|
46
|
+
supported threat model is. A finding that contradicts a documented,
|
|
47
|
+
intentional design is a policy question, not a confirmed vuln.
|
|
48
|
+
2. **Classify the surface under review**:
|
|
49
|
+
- `product_surface`: hosted service | library API | CLI | local dev UI |
|
|
50
|
+
MCP/tooling | example/demo | test | docs | generated | vendored.
|
|
51
|
+
- `source_trust` of the input: untrusted (remote/attacker) |
|
|
52
|
+
trusted_operator | trusted_developer_config | local_only |
|
|
53
|
+
intentional_code_execution.
|
|
54
|
+
- `boundary_crossed`: does attacker-controlled input reach the sink across a
|
|
55
|
+
real privilege/trust boundary? true | false | unknown.
|
|
56
|
+
3. **Gate**: no boundary crossed (attacker == victim, same privilege, local dev
|
|
57
|
+
tool with no request handler) → NOT a finding. Record the disposition in the
|
|
58
|
+
coverage ledger, do not emit it as LOW.
|
|
59
|
+
|
|
60
|
+
### SECTION: threat-model
|
|
61
|
+
|
|
62
|
+
Establish (or adopt) a **repository-scoped** threat model — deliberately NOT
|
|
63
|
+
biased by the current diff, so it stays valid for any change in the same repo.
|
|
64
|
+
|
|
65
|
+
- **Adopt** an existing model from the user, `SECURITY.md`, or `AGENTS.md` when
|
|
66
|
+
present. Only **generate** a fallback when none exists.
|
|
67
|
+
- Fallback generation, repository-level (not diff-scoped):
|
|
68
|
+
1. Real-world purpose + primary product/runtime surfaces actually exposed
|
|
69
|
+
(separate them from test/demo/tooling/docs paths).
|
|
70
|
+
2. Trust boundaries + the actors on each side; separate **attacker-controlled**
|
|
71
|
+
vs **operator-controlled** vs **developer-controlled** inputs explicitly.
|
|
72
|
+
3. Sensitive assets: user data, auth artifacts, authorization state,
|
|
73
|
+
secrets/keys, config, models/weights, audit logs, availability-critical
|
|
74
|
+
resources, tenant-isolation state.
|
|
75
|
+
4. Vulnerability CLASSES relevant to this repo's context (not the diff's
|
|
76
|
+
findings) + existing mitigations grounded in real files.
|
|
77
|
+
5. When realistic vs out-of-scope: state attacker (non-)capabilities so
|
|
78
|
+
severity is not inflated.
|
|
79
|
+
- Use it to pick **focus paths** for the review; do not let the diff recenter it
|
|
80
|
+
unless the user asks for a diff-scoped model.
|
|
81
|
+
|
|
82
|
+
### SECTION: discovery-lens
|
|
83
|
+
|
|
84
|
+
Beyond the OWASP core checklist (in the agent body), sweep for the **modern
|
|
85
|
+
high-miss patterns** — the ones a generic checklist walks past. For each changed
|
|
86
|
+
region, ask:
|
|
87
|
+
|
|
88
|
+
- **FAIL-OPEN state drift**: a default that *allows* on the unknown/error path —
|
|
89
|
+
catch-all `default: allow`, `unwrap_or({})`, a removed `finally` that left the
|
|
90
|
+
deny, an early-return before the check. Security must fail *closed*.
|
|
91
|
+
- **ALLOWLIST semantic escape**: a matcher weakened — a `||`/disjunction added, a
|
|
92
|
+
regex left unanchored (`^…$` missing), an allowlist checked by `startsWith`/
|
|
93
|
+
substring, a URL trusted by substring instead of parsed host.
|
|
94
|
+
- **CONTROL regression**: a deny-by-default replaced by a single positive
|
|
95
|
+
condition; an authz/confirm/audit control loosened or removed in the diff.
|
|
96
|
+
- **GATE / ACTION field mismatch**: the gate checks resource A (parent, id X) but
|
|
97
|
+
the action writes/reads resource B (child, id Y) — the check and the effect
|
|
98
|
+
disagree.
|
|
99
|
+
- **UNDER-VALIDATED sink arg**: user data flows into sink arg *X* while a sibling
|
|
100
|
+
path validates arg *Y* — asymmetry between siblings is the tell.
|
|
101
|
+
- **PARSER/VALIDATOR differential**: the validator and the consumer parse the
|
|
102
|
+
input differently (two URL parsers, JSON vs form, unicode/normalization) — the
|
|
103
|
+
gap is the exploit.
|
|
104
|
+
- **SENSITIVE-to-observability**: secrets/tokens/PII reaching logs, traces,
|
|
105
|
+
error responses, analytics, crash dumps.
|
|
106
|
+
- **CI/CD trust**: `pull_request_target` / `workflow_dispatch` / injectable
|
|
107
|
+
`${{ github.event.*.body }}` combined with secrets or repo-write; a workflow
|
|
108
|
+
running untrusted code with elevated tokens.
|
|
109
|
+
- **IaC omitted arg**: a Terraform/CDK/K8s resource missing a security flag
|
|
110
|
+
(public bucket, open SG, no encryption, over-broad IAM `*`).
|
|
111
|
+
- **OVER-BROAD grant**: an admin/`*` role/scope where a narrower one exists;
|
|
112
|
+
new IAM/RLS/role wider than the action needs.
|
|
113
|
+
- **STALE identity mapping**: a window between unregister/rotate and the new
|
|
114
|
+
binding where the old identity still resolves.
|
|
115
|
+
- **SECURITY-REGISTRY fanout**: a new entity type (model, scope, route, event)
|
|
116
|
+
added but missing from the sanitizer/allowlist/authz registries that must
|
|
117
|
+
enumerate it.
|
|
118
|
+
- **RESOURCE-bound placement**: a cap/limit on the wrong accumulator; an
|
|
119
|
+
under/overflow; a size check after the allocation.
|
|
120
|
+
|
|
121
|
+
### SECTION: proof-tuples
|
|
122
|
+
|
|
123
|
+
A security finding is a *hypothesis* until its **class-specific proof tuple** is
|
|
124
|
+
grounded against real code (this is the AppSec form of the CoVe pass). Confirm
|
|
125
|
+
every element by grep/read before emitting; drop the finding if any element is
|
|
126
|
+
missing.
|
|
127
|
+
|
|
128
|
+
- **authz / IDOR**: attacker reachability path + the missing/bypassed guard + the
|
|
129
|
+
protected object or state it exposes.
|
|
130
|
+
- **injection** (SQL/NoSQL/OS/LDAP/template): attacker-controlled bytes + the
|
|
131
|
+
sanitizer/parameterization result (or its absence) + the dangerous sink.
|
|
132
|
+
- **deserialization**: attacker serialized input + the unsafe loader + the
|
|
133
|
+
execution/instantiation effect.
|
|
134
|
+
- **SSRF / open redirect**: attacker-controlled destination + the control bypass
|
|
135
|
+
+ the network reach / side effect.
|
|
136
|
+
- **auth / token**: attacker-supplied value + the validator's exact semantics +
|
|
137
|
+
the mismatch with the trusted value.
|
|
138
|
+
- **XSS**: attacker string + the encoding/escaping context at output + the sink
|
|
139
|
+
(`innerHTML`/`dangerouslySetInnerHTML`/template) with no encode.
|
|
140
|
+
|
|
141
|
+
**Confidence anchored to validation METHOD, never to how scary the bug class
|
|
142
|
+
sounds**:
|
|
143
|
+
- reproduced PoC / failing test that triggers the sink → confidence 90–100.
|
|
144
|
+
- debugger/trace or a proven interface reproduction → 75–90.
|
|
145
|
+
- static source→sink trace fully grounded in read code → 60–80.
|
|
146
|
+
- code-understanding argument with a defensible but not fully-traced path →
|
|
147
|
+
30–55. Below that, it is a hypothesis — do not ship as HIGH.
|
|
148
|
+
|
|
149
|
+
**Instance-preserving**: do NOT collapse independently exploitable sibling
|
|
150
|
+
instances (`execute` / `executemany` / `executescript`; two routes with the same
|
|
151
|
+
flaw) into one finding. Each independently triggerable sink gets its own
|
|
152
|
+
finding/closure row.
|
|
153
|
+
|
|
154
|
+
### SECTION: attack-path
|
|
155
|
+
|
|
156
|
+
BEFORE assigning severity, write the attack path as **structured facts**, then
|
|
157
|
+
let severity fall out of them mechanically (`review-protocol.md
|
|
158
|
+
SECTION=risk-scoring`) — this stops severity from being argued emotionally.
|
|
159
|
+
|
|
160
|
+
- `attacker`: who, at what trust level, from where.
|
|
161
|
+
- `entrypoint`: the exact reachable entry (route/RPC/CLI/webhook/MCP tool).
|
|
162
|
+
- `preconditions`: conditions that must hold for the exploit (feature flag on,
|
|
163
|
+
authenticated user, specific config). A **precondition** narrows likelihood but
|
|
164
|
+
does NOT refute — keep it distinct from counterevidence (which kills the
|
|
165
|
+
finding, see `adversarial-refute`).
|
|
166
|
+
- `dataflow`: source → sink in one line.
|
|
167
|
+
- `outcome`: the concrete impact (data read/written, code executed, tenant
|
|
168
|
+
crossed).
|
|
169
|
+
- `impact` (1–5) and `likelihood` (1–5), each with one line of repo evidence.
|
|
170
|
+
|
|
171
|
+
Severity is then `review-protocol.md SECTION=risk-scoring` applied to
|
|
172
|
+
`impact × likelihood` — do not re-argue it afterward.
|
|
173
|
+
|
|
174
|
+
### SECTION: adversarial-refute
|
|
175
|
+
|
|
176
|
+
The security-specialized layer of the generic Challenge pass. Stance: **a finding
|
|
177
|
+
SURVIVES unless you produce concrete refuting evidence** — but the single most
|
|
178
|
+
common false positive is a **missing privilege boundary**, so test that first.
|
|
179
|
+
|
|
180
|
+
**Privilege-boundary test (BINDING)**: name the attacker (who controls the input)
|
|
181
|
+
and the victim (who is harmed). If attacker == victim operating on their own
|
|
182
|
+
machine / same-privilege process (a CLI arg in a same-trust process, a dev
|
|
183
|
+
script, a local tool with no remote entrypoint) → **REFUTE**. Keep it only when
|
|
184
|
+
the attacker is a lower-trust actor and the impact reaches other users, tenants,
|
|
185
|
+
or infrastructure.
|
|
186
|
+
|
|
187
|
+
**Refute the finding when**:
|
|
188
|
+
- it is **pre-existing** code untouched by the diff (in diff-scoped review, flag
|
|
189
|
+
only newly introduced or newly reachable surface; an off-diff finding must name
|
|
190
|
+
the specific `+`/`-` line that enables the sink).
|
|
191
|
+
- a sanitizer / validator / parameterization / authz check on the real path
|
|
192
|
+
already prevents the exploit.
|
|
193
|
+
- the sink is not actually dangerous here (typed-schema decoder, hardcoded
|
|
194
|
+
`https` URL, ORM/parameterized query, non-HTML context for an "XSS").
|
|
195
|
+
- a frontend-only gate is independently enforced by the backend (or vice-versa).
|
|
196
|
+
- validation is delegated to a caller/framework that provably runs it.
|
|
197
|
+
- it is throwaway/dev-only code (`scripts/`, `dev/`, `__main__`, fixtures, tests)
|
|
198
|
+
with no shipped surface.
|
|
199
|
+
- a dependency bump moved the control into the library (documented).
|
|
200
|
+
|
|
201
|
+
**Precondition vs counterevidence (keep precise)**: "deployment is internal-only"
|
|
202
|
+
is a *precondition* on the finding (still exploitable if it holds) → keep, lower
|
|
203
|
+
likelihood. "the code is test-only" is *counterevidence* → refute. Do not confuse
|
|
204
|
+
the two.
|
|
205
|
+
|
|
206
|
+
**Never-refute guard**: an item the agent's never-demote list marks (auth bypass,
|
|
207
|
+
RCE, secret exposure, cross-tenant breach with a grounded proof tuple) is never a
|
|
208
|
+
false positive — do not refute it however convincing the argument sounds.
|
|
209
|
+
|
|
210
|
+
Record refuted candidates (title + one-line refutation) so the audit trail shows
|
|
211
|
+
they were considered, not missed.
|
|
212
|
+
|
|
213
|
+
### SECTION: coverage-ledger
|
|
214
|
+
|
|
215
|
+
Make the review's *coverage* explicit so a clean verdict is honest and a gap is
|
|
216
|
+
never silent. For each security-relevant surface in scope, record a disposition:
|
|
217
|
+
|
|
218
|
+
- `reported` — a finding was emitted.
|
|
219
|
+
- `no_issue_found` — reviewed, no credible issue survived the passes.
|
|
220
|
+
- `not_applicable` — the class does not apply to this surface (with the reason).
|
|
221
|
+
- `needs_follow_up` — a real concern out of this review's scope/ownership
|
|
222
|
+
(surfaces as residual).
|
|
223
|
+
- `deferred` — could not complete (tool/access/time), with the reason + paths.
|
|
224
|
+
|
|
225
|
+
Rules:
|
|
226
|
+
- A **complete** review has zero `deferred` / `needs_follow_up` rows; otherwise
|
|
227
|
+
it is **partial** — say so. Zero findings on a fully-covered surface is a
|
|
228
|
+
legitimate, reportable outcome.
|
|
229
|
+
- A seeded obligation (a CVE/advisory/user pointer at a specific file/function)
|
|
230
|
+
stays OPEN until its exact row is closed as reported / not_applicable /
|
|
231
|
+
deferred — a neighboring same-family finding does not close it.
|
|
232
|
+
- In the pooled YAML mode, carry this as a compact `coverage:` block in the
|
|
233
|
+
`# Security Review Summary` header, not as fake LOW findings.
|
|
@@ -55,72 +55,76 @@ Document security requirements, threats, and mitigation strategies.
|
|
|
55
55
|
- [Sensitive data masking in logs]
|
|
56
56
|
- [Secrets management]
|
|
57
57
|
|
|
58
|
-
## Common Vulnerabilities (OWASP Top 10)
|
|
58
|
+
## Common Vulnerabilities (OWASP Top 10 — 2021)
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
> Modernized to the OWASP Top 10:2021 categories (the 2017 list — with XXE and
|
|
61
|
+
> "Sensitive Data Exposure" as standalone entries — is superseded). XXE now folds
|
|
62
|
+
> into Security Misconfiguration; insecure deserialization into Software & Data
|
|
63
|
+
> Integrity Failures; XSS into Injection. A 2025 revision is in draft — revisit
|
|
64
|
+
> when it is finalized (expected consolidation of supply-chain risks).
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
- Validate and sanitize inputs
|
|
64
|
-
- Implement least privilege database access
|
|
66
|
+
### A01 Broken Access Control
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
- Enforce authorization on every request, server-side; deny by default
|
|
69
|
+
- Prevent IDOR — never trust a user-supplied record/object identifier
|
|
70
|
+
- Enforce ownership + tenant isolation on every sensitive action
|
|
71
|
+
- Principle of least privilege; no privilege escalation via business logic
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
- Use strong password policies
|
|
70
|
-
- Implement account lockout
|
|
71
|
-
- Protect against brute force
|
|
73
|
+
### A02 Cryptographic Failures
|
|
72
74
|
|
|
73
|
-
|
|
75
|
+
- Encrypt sensitive data at rest and in transit (HTTPS/TLS everywhere)
|
|
76
|
+
- Use strong, modern algorithms (no MD5/SHA1 for security, no AES-ECB, no static IV)
|
|
77
|
+
- Proper key management + rotation; never log secrets or PII
|
|
78
|
+
- Strong password hashing (argon2/bcrypt/scrypt) with per-user salt
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
- Use HTTPS everywhere
|
|
77
|
-
- Don't log sensitive information
|
|
78
|
-
- Implement secure key management
|
|
80
|
+
### A03 Injection (incl. XSS)
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
- Parameterized queries / ORM; never build queries by string concatenation
|
|
83
|
+
- Validate + sanitize inputs; allowlists over denylists
|
|
84
|
+
- Least-privilege database access
|
|
85
|
+
- Output encoding at the right context + Content Security Policy for XSS
|
|
81
86
|
|
|
82
|
-
|
|
83
|
-
- Use safe XML parsers
|
|
84
|
-
- Validate XML inputs
|
|
87
|
+
### A04 Insecure Design
|
|
85
88
|
|
|
86
|
-
|
|
89
|
+
- Threat-model the feature before building; secure-by-default patterns
|
|
90
|
+
- Establish trust boundaries and enforce them; fail closed
|
|
91
|
+
- Rate limits, resource bounds, and abuse cases considered up front
|
|
87
92
|
|
|
88
|
-
|
|
89
|
-
- Validate permissions on every request
|
|
90
|
-
- Use principle of least privilege
|
|
93
|
+
### A05 Security Misconfiguration (incl. XXE)
|
|
91
94
|
|
|
92
|
-
|
|
95
|
+
- Harden defaults; remove unnecessary features/debug endpoints in prod
|
|
96
|
+
- Set security headers; keep software updated
|
|
97
|
+
- Disable XML external-entity processing; use safe parsers/validators
|
|
93
98
|
|
|
94
|
-
|
|
95
|
-
- Keep software updated
|
|
96
|
-
- Remove unnecessary features
|
|
97
|
-
- Implement security headers
|
|
99
|
+
### A06 Vulnerable & Outdated Components
|
|
98
100
|
|
|
99
|
-
|
|
101
|
+
- Keep dependencies patched; monitor security advisories (CVE/GHSA)
|
|
102
|
+
- Run dependency + vulnerability scanning in CI (e.g. audit / govulncheck)
|
|
103
|
+
- Remove unused dependencies and features
|
|
100
104
|
|
|
101
|
-
|
|
102
|
-
- Use Content Security Policy
|
|
103
|
-
- Validate and sanitize inputs
|
|
104
|
-
- Use framework protections
|
|
105
|
+
### A07 Identification & Authentication Failures
|
|
105
106
|
|
|
106
|
-
|
|
107
|
+
- Secure session management (rotation, expiry, secure cookies)
|
|
108
|
+
- Strong password policy, account lockout / brute-force protection, MFA where applicable
|
|
109
|
+
- No session fixation, no token leakage in URLs/logs
|
|
107
110
|
|
|
108
|
-
|
|
109
|
-
- Use safe deserialization libraries
|
|
110
|
-
- Implement integrity checks
|
|
111
|
+
### A08 Software & Data Integrity Failures (incl. insecure deserialization)
|
|
111
112
|
|
|
112
|
-
|
|
113
|
+
- Never deserialize untrusted data with unsafe loaders; validate + integrity-check
|
|
114
|
+
- Verify integrity of updates/CI artifacts (signatures, SRI, pinned digests)
|
|
115
|
+
- Guard the CI/CD supply chain — no untrusted code with elevated tokens
|
|
113
116
|
|
|
114
|
-
|
|
115
|
-
- Monitor security advisories
|
|
116
|
-
- Use dependency scanning tools
|
|
117
|
+
### A09 Security Logging & Monitoring Failures
|
|
117
118
|
|
|
118
|
-
|
|
119
|
+
- Log security events; monitor for suspicious activity; alert
|
|
120
|
+
- Protect log integrity; never log secrets/PII
|
|
121
|
+
- Ensure exploitation attempts are detectable and auditable
|
|
119
122
|
|
|
120
|
-
-
|
|
121
|
-
|
|
122
|
-
-
|
|
123
|
-
-
|
|
123
|
+
### A10 Server-Side Request Forgery (SSRF)
|
|
124
|
+
|
|
125
|
+
- Validate + allowlist outbound destinations; parse (don't substring) URLs
|
|
126
|
+
- Block internal metadata endpoints and private ranges
|
|
127
|
+
- Enforce egress controls; treat any user-supplied URL/host as hostile
|
|
124
128
|
|
|
125
129
|
## Rate Limiting
|
|
126
130
|
|