cve-audit — dependency-vulnerability audit
The engine is cve-audit.js (portable Node, zero deps). The advisory data is
live — npm audit reaches the npm registry and pip-audit its own database, and
what they return moves as advisories publish. The deterministic, canary-pinned
part is the PARSE + REPORT layer: the severity bucketing, the counts, and the
fail-level→exit-code logic. That is what makes this usable as a release gate and
what the canary proves.
Typical target: a Next.js/TypeScript frontend (npm) paired with a FastAPI/Python backend (pip). Both ecosystems, one auditor. When the backend holds sensitive user data, a high/critical advisory in a request-handling dependency is a launch blocker, not a nag.
Commands
node cve-audit.js [--dir <path>] [--fail-level critical|high|moderate|low]
node cve-audit.js --fixture <npm-audit.json> [--fail-level <lvl>]
node cve-audit.js --canary
- default (auto-detect): audits
--dir(default cwd). Runsnpm audit --jsonwhenpackage.json+ a lockfile are present, andpip-audit --format jsonwhenrequirements.txt/pyproject.toml/poetry.lockis present. If both exist, both run. Prints a severity table; exits 1 when any finding is at/above the fail-level. - --fixture parses a SAVED
npm audit --jsonfile offline — no network. Use it on a CI-captured audit log, or to reproduce a result deterministically. This is the mode the canary exercises. - --fail-level sets the gate (default
high):highfails on any high or critical;criticalfails only on critical;lowfails on anything.
Examples
- Gate a Next.js frontend (npm):
node cve-audit.js --dir /path/to/frontend --fail-level high— a high/critical advisory exits 1 and blocks the release. - Audit a FastAPI backend (Python):
same command in the backend dir runs
pip-audit. If pip-audit isn't installed the run reportsMISSING: pip-audit is not on PATHwithpipx install pip-auditand exits 2 — it never pretends the backend is clean. - Re-check a CI audit log offline:
node cve-audit.js --fixture ci/npm-audit.json --fail-level critical— parses the captured JSON with no registry call, applies the same gate logic.
What each ecosystem reports
- npm (audit v2 schema): a table of
critical / high / moderate / lowwith the vulnerable package names and per-severity counts, plus a total. Fail-level logic runs on those counts. - pip-audit: its default JSON carries no CVSS severity, so cve-audit reports vulnerable-package and total-advisory counts; ANY finding fails the run (fail-level does not sub-divide it).
Windows notes
npm auditshells out tonpm(npm.cmdon Windows) — it must be on PATH.pip-auditis checked withwhere pip-audit(which pip-auditon POSIX); if it is not installed, the Python path correctly reports MISSING rather than a false all-clear.- The
--fixturemode is pure file parsing — no shell, safe everywhere.
Storage / output
No files are written. Output is the severity table + verdict on stdout; errors and
the MISSING notice go to stderr. The bundled fixture.json (an npm-audit v2 sample:
1 high, 1 moderate, 1 low) is shipped only as an offline --fixture example.
Exit codes
0 clean or all findings below fail-level · 1 a finding at/above the fail-level
(or canary failure) · 2 usage error / audit tool missing / unparseable input.
Verification (the done-check)
node cve-audit.js --canary
Drives the parse/report core off a temp npm-audit fixture in BOTH directions — a
fail-level high run with a high finding exits 1 (catches), a fail-level critical
run with no critical exits 0 (stays quiet) — plus exact severity counts, clean-input
pass, malformed-input exit 2, and pip-audit parsing. No network, no npm, no pip.
MUST print CANARY PASS n/n before you trust a result.