Commit 3ebb5ba
ci(audit): H-5 — pip-audit gate + Snyk fail-mode (#102)
* ci(audit): H-5 — pip-audit gate + Snyk fail-mode (no more silent vuln pass)
Audit H-5 (`tasks/compliance-audit-2026-04-25.md`):
- snyk-security.yml had `|| true` on both `snyk code test` and
`snyk test` so HIGH/CRITICAL CVE findings shipped silently.
- No `pip-audit` CI step existed; SCA only ran when SNYK_TOKEN was
set as a repo secret. The branch where SNYK_TOKEN is unset
(e.g., forks, low-budget repos) had zero supply-chain coverage.
GOV-009 §"Vulnerability Response" mandates HIGH/CRITICAL CVEs be
patched within 48h. The 48h SLO requires an alarm to start the
clock; this PR provides one for both Snyk-token and no-token paths.
Changes:
1. `.github/workflows/snyk-security.yml`
- Drop `|| true` on both Snyk steps. Real findings now fail.
- Add `--severity-threshold=high` so MEDIUM stays advisory and
only HIGH/CRITICAL block (matches GOV-009's threshold).
- Switch `snyk code test --sarif > snyk-code.sarif` to
`--sarif-file-output=snyk-code.sarif` so SARIF is still emitted
when the test fails — needed for the subsequent SARIF upload
step to publish findings even when CI is red.
2. `.github/workflows/ci.yml`
- New `pip-audit` job that runs on every PR. Token-free, uses
OSV vulnerability service, fails non-zero on any reported vuln.
Fast (under 30s) and complements Snyk for the no-token path.
Inline comment documents how to add `--ignore-vuln=GHSA-...`
for accepted-risk exclusions per GOV-009.
This closes audit H-5. Master CI now has a gate that maps to
GOV-009 + GOV-011 §"Testing Phase" + FedRAMP SA-12, SI-2, SR-3.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ci: register GOV-009 in controls.yaml + ignore pip-itself CVE-2026-3219
Two follow-ups to the H-5 PR after CI surfaced concrete issues:
1. test_no_phantom_controls_in_ci.py failed because the GOV-009
reference in ci.yml's pip-audit step had no corresponding entry
in governance/controls.yaml. Spec-drift check correctly caught
the orphan reference. Added the GOV-009 control with three
rules — pip-audit, Snyk SCA, Snyk SAST — each linked to the
exact CI step name and tool string. Closes the spec-drift gap.
2. pip-audit found CVE-2026-3219 in `pip 26.0.1` itself (the
package manager). This isn't a ZettelForge dependency that we
can pin or upgrade — pip is shipped by GitHub's setup-python
image. Risk-accepted with --ignore-vuln=CVE-2026-3219 plus an
inline citation explaining the surface (install-time, not
runtime; ephemeral runners; re-evaluate when GitHub patches
the image). Matches the GOV-009 risk-acceptance pattern the
workflow comment already documents.
test_governance_spec_drift.py passes locally with these changes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 7fac1ac commit 3ebb5ba
3 files changed
Lines changed: 57 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
32 | 63 | | |
33 | 64 | | |
34 | 65 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
47 | 54 | | |
48 | 55 | | |
49 | | - | |
| 56 | + | |
50 | 57 | | |
51 | 58 | | |
52 | 59 | | |
53 | 60 | | |
54 | 61 | | |
55 | | - | |
| 62 | + | |
56 | 63 | | |
57 | 64 | | |
58 | 65 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
37 | 54 | | |
38 | 55 | | |
39 | 56 | | |
| |||
0 commit comments