'Why I stopped trusting npm audit (and built my own)'
Source: Dev.to
Generate a CycloneDX SBOM and deterministic, audit‑ready risk report from your package-lock.json
You run npm audit. It says “47 vulnerabilities.”
Cool. Which ones actually matter? The one in your production bundle? You don’t know.
So you either:
- Ignore everything → ship anyway
- Lose signal either way
The real problem isn’t vulnerabilities — it’s decision‑making.
The real problem isn’t vulnerabilities — it’s decision‑making
Most tools answer:
“What is wrong?”
They don’t answer:
“What should I do about it?”
That last question is the real problem.
Enter: audit‑ready
Instead of scores, it gives you decisions. Deterministic. Reproducible. Auditable.
🔑 reasonCode replaces CVSS
Every dependency gets exactly one label, e.g.:
DEV_DEPENDENCY_ONLY
No interpretation required. CI becomes trivial – not “7 high vulnerabilities.”
🧠 The constraint that shapes everything
Same package-lock.json → identical output. Always.
How that’s enforced
Core logic has hard constraints:
const banned = ['Date', 'Date.now()', 'Math.random()', 'process.env'];
If determinism breaks → build fails.
⚙️ The engine is intentionally simple
No scoring. No heuristics.
First match wins – priority is defined by rule order.
🧾 Output you can actually use
Everything is tied to reasonCode.
🔐 Security: this tool audits itself
If you’re generating audit artifacts, your tool has to be trustworthy.
No environment access
The core engine literally cannot read:
- environment variables
Output depends only on input + tool version
Deterministic PURL generation
Standard encoders (encodeURIComponent, URL) can differ across Node versions, so PURLs are built manually.
- Same package → same PURL → always
Schema validation (input + output)
If validation fails → nothing is written.
Immutable output
No silent mutation. Exceptions cannot live forever; every exception requires a reason. Expired? audit-ready audit-exceptions → exit 1. No silent ignores.
Network safety by design
Only one external call:
- OSV API with PURLs
If it fails, the SBOM is still generated. The tool runs its own pipeline on itself – same code, same rules. If it lies, it exposes itself.
⚠️ What this tool does NOT do
If a case isn’t covered → it fails loudly.
Why this matters
This isn’t about better scanning. It’s about reproducible decisions. Production release planned after Phase 3.
💬 Looking for feedback
https://github.com/neve7er/audit-ready
Final thought
Most tools try to be smart. This one tries to be predictable. Because in security, predictability beats intelligence.