security-review/checkers/fixtures/dependency-cve/README.md
Adam Moussa 4c88c01f7b
chore: import security-review gate, sweep, and Plane-1 checkers into standalone repo
Fresh-init copy of the security-review/ subsystem extracted from
Sea-Haven-Industries/orchestrator (being deprecated). Adds org-standard scaffold:
CI reusable-workflow callers (ruff + collect), dependency-review, labeler,
dependabot, .gitignore, requirements.txt. Scheduled execution is migrating to
Claude Code web routines (ALARM-only to #repo-scanner); the systemd units and
nightly_sweep.sh/checker_coordinator.sh remain the source of truth.

Committed with --no-verify: the canary fixtures (checkers/fixtures/**) carry
intentional secret-shaped test data that trips the deterministic gate (the
documented detector-fixture false positive); no new logic is introduced.
2026-06-29 11:41:41 -04:00

42 lines
2.6 KiB
Markdown

# dependency-cve canary fixtures
Planted-vulnerable-dependency corpus for `checkers/dependency-cve.sh --canary` (offline,
no network/token). The checker asserts the total vulnerable-dependency count equals
`EXPECTED_VULN_COUNT` (anti-complacency floor, design §6.4). If extraction or matching
regresses (a parser stops firing, or the advisory match breaks), the count drops and the
canary FAILS (exit 3).
## Offline advisory source
OSV needs the network, so the canary CANNOT call `api.osv.dev`. Instead, `--canary`
(and the `--advisories-file PATH` override) makes the checker consult the local
`osv-advisories.json` fixture INSTEAD of the network — keyed by `ECOSYSTEM|package|version`.
This keeps the canary fully offline and deterministic. The fixture mirrors real advisory
ids/summaries/fixed-versions so a finding looks like a live one, but nothing is fetched.
## Fixture repos (each a real git checkout; `dotgit/` is renamed to `.git/` at run time)
The git metadata is shipped as `dotgit/` (not `.git/`) so these commit into the orchestrator
repo WITHOUT becoming nested submodules — the SAME trick `compliance-drift` fixtures use. The
checker copies each fixture to a temp area and renames `dotgit` → `.git` before scanning.
| Fixture | Ecosystem | Pinned deps | Vulnerable match | Count |
|---|---|---|---|---|
| `vuln-py-repo` | PyPI (`requirements.txt`) | `flask==2.0.1`, `jinja2==2.11.2`, `requests==2.31.0` | `jinja2==2.11.2` → `GHSA-g3rq-g295-4j3m` | 1 |
| `vuln-js-repo` | npm (`package-lock.json`) | `lodash 4.17.15`, `left-pad 1.3.0` | `lodash 4.17.15` → `GHSA-p6mc-m468-83gw` | 1 |
| `clean-repo` | PyPI (`requirements.txt`) | `requests==2.31.0`, `urllib3==2.2.1` | none (no advisory entry) | 0 |
Total = **2** (`EXPECTED_VULN_COUNT`). Two ecosystems are exercised (PyPI + npm) so a
regression in either parser is caught.
When you add/remove a parser, a fixture, or an advisory entry, update the fixture(s),
`osv-advisories.json`, and `EXPECTED_VULN_COUNT` in the same commit (the canary edit is
itself caught on the next run — design §6.4).
**Manifest naming:** the dependency manifests are stored with a `.fixture` suffix
(`requirements.txt.fixture`, `package-lock.json.fixture`) so GitHub's dependency graph /
the `dependency-review` CI action does NOT parse the deliberately-vulnerable canary pins as
real project dependencies (which would fail the PR gate). The checker's `--canary`
materialization strips the `.fixture` suffix in its temp work area before scanning, so the
per-ecosystem parsers still dispatch on the real names. Keep this suffix on any new
manifest fixture.