Dependency Security for JavaScript and TypeScript: From npm audit to a Fix You Can Trust
Something in your project just got flagged as vulnerable. Maybe a Dependabot PR opened overnight, maybe a commercial scanner lit up in CI, maybe it was the summary every npm install prints - a count of high-severity advisories and a nudge to run npm audit for details. However it reached you, npm audit is where you go to see the damage:
# npm audit report
axios <=0.32.0
Severity: high
axios Requests Vulnerable To Possible SSRF and Credential Leakage via Absolute URL - https://github.com/advisories/GHSA-jr5f-v2jv-69x6
Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF - https://github.com/advisories/GHSA-3p68-rc4w-qgx5
Axios: Authentication Bypass via Prototype Pollution Gadget in validateStatus Merge Strategy - https://github.com/advisories/GHSA-w9j2-pvgh-6h63
Axios: Prototype Pollution Gadgets - Response Tampering, Data Exfiltration, and Request Hijacking - https://github.com/advisories/GHSA-pf86-5x62-jrwf
Axios is Vulnerable to Denial of Service via __proto__ Key in mergeConfig - https://github.com/advisories/GHSA-43fc-jf86-j433
... and 19 more axios advisories ...
fix available via `npm audit fix --force`
Will install axios@0.21.4, which is outside the stated dependency range
node_modules/axios
form-data <=2.5.5
Severity: critical
form-data uses unsafe random function in form-data for choosing boundary - https://github.com/advisories/GHSA-fjxv-7rqg-78g4
No fix available
request *
Depends on vulnerable versions of form-data
Depends on vulnerable versions of qs
node_modules/request
You have seen this screen. Whatever raised the alarm, npm audit is where you land when you try to actually fix it - and it is where the report stops helping. Two paths from here: spend the next hour reverse-engineering the dependency tree by hand, or ship anyway and promise yourself you will come back to it. Most teams come back never.
This guide walks that exact failure end to end - not just what is vulnerable, but what to actually run - using CVE Lite CLI, an OWASP Lab Project built specifically to close that gap.
Everything in this guide runs on one real project you can clone, so every command below is reproducible - acme-api, a tiny Node service with four intentionally outdated dependencies. The wall above is its actual npm audit output:
git clone https://github.com/sonukapoor/acme-api.git && cd acme-api
npm audit # the report above
Here is the thing worth saying out loud: npm audit is not wrong. Every line is true, and running it at all puts you ahead of most teams. axios really is behind on two dozen advisories. form-data really is critical. The problem is not what it reports. The problem is what it tells you to do.
Read what the fix actually says
For axios, the offered fix is npm audit fix --force. So you take it. The first line it prints is a warning that it is switching off its own recommended protections, and then it rewrites your package.json:
npm warn using --force Recommended protections disabled.
npm warn audit Updating axios to 0.21.4, which is outside your stated dependency range.
npm warn audit Updating lodash to 4.18.1, which is outside your stated dependency range.
npm warn audit Updating minimist to 1.2.8, which is outside your stated dependency range.
npm warn audit No fix available for request@*
changed 3 packages, and audited 52 packages in 734ms
It disabled its own protections and installed axios@0.21.4 - a version still inside the vulnerable <=0.32.0 range.
Then it re-audits what it just installed, and the whole wall of advisories is still there:
axios <=0.32.0
Severity: high
... the same 24 advisories, again ...
fix available via `npm audit fix --force`
Will install axios@1.19.0, which is a breaking change
Read that carefully. It turned off its own safety, rewrote your manifest, left you exactly as exposed as before - and now, still red, it wants you to run --force again, this time into axios@1.19.0, "a breaking change." One forced step that did nothing, and a breaking major waiting behind it. npm audit reports what is in range of an advisory; it was never built to find the version that is actually clean and land you there in one move.
For form-data, it is blunter:
form-data <=2.5.5
Severity: critical
No fix available
A critical vulnerability, and a dead end. form-data is transitive - request pulls it in - but npm audit will not tell you whether upgrading request helps, or why form-data cannot be fixed. You are on your own.
This is the gap. npm audit answers "what is in range of an advisory?" It does not answer the only question that matters once you are the one who has to fix it: what do I run to make this go away? Those are two different questions, and audit was built for the first.
Now run CVE Lite CLI on the same project
Let's run CVE Lite CLI on that same lockfile and see what it does with the same eight packages. It is free, open source (MIT), and an OWASP Lab Project (OWASP's mid-tier maturity rating, above Incubator):
npm install -g cve-lite-cli
cve-lite .
Package manager: npm (package-lock.json)
────────────────────────────────
📦 Vulnerabilities found
────────────────────────────────
CRITICAL minimist@1.2.0
Direct dependency
Fix: upgrade to 1.2.6
CRITICAL form-data@2.3.3
Transitive dependency
Fix: Upgrade request — check for release resolving form-data to 2.5.6+
HIGH axios@0.21.1
Direct dependency
Fix: upgrade to 0.33.0
────────────────────────────────
Summary
────────────────────────────────
8 packages · 38 CVEs
2 critical · 2 high · 4 medium
4 direct · 4 transitive
It reads your lockfile locally and checks package names and versions against OSV - your source never leaves your machine. Same eight packages npm audit found. But look at axios: the fix is 0.33.0, not the 0.21.4 that npm audit fix --force wanted to install.
A fix you can trust, not just "upgrade"
Why 0.33.0 and not 0.21.4? Run --verbose and the fix plan shows its work:
| Severity | Package | Current | Target | Versions scanned | Still known vulnerable |
|---|---|---|---|---|---|
| critical | minimist | 1.2.0 | 1.2.6 | 6 | 5 |
| high | axios | 0.21.1 | 0.33.0 | 23 | 22 |
| high | lodash | 4.17.15 | 4.18.0 | 8 | 7 |
npm install minimist@1.2.6 # critical
npm install axios@0.33.0 lodash@4.18.0 # high
Those Versions scanned and Still known vulnerable columns are the whole game. In one command - no --force, nothing disabled, nothing rewritten - it checked all 23 published axios releases above yours, found that 22 of them still carry a known advisory, and handed you the first that does not: 0.33.0. That is the version npm audit never offered - it stepped straight over it, from a useless 0.21.4 to a breaking 1.19.0. And you do not have to trust the recommendation: the 22 of 23 is the receipt.
That 0.33.0 is not arbitrary: every advisory affects <=0.32.0, so it is the first release past the vulnerable range - the lowest version that clears every one of them, not the newest one that happens to. The same walk gives minimist a small hop (5 of the next 6 releases are still vulnerable; 1.2.6 is clean) and axios a long one - and telling you exactly how long, instead of hand-waving "upgrade," is the point.
The dead end, explained
Now form-data - the critical one npm audit gave up on with "No fix available." CVE Lite CLI reports it against the parent you actually control:
CRITICAL form-data@2.3.3
Transitive dependency
Fix: Upgrade request — check for release resolving form-data to 2.5.6+
So the move is to upgrade request. Except the same --verbose run adds one more line:
Unpublishable fixed-version hints:
- request@2.88.2: Advisory fixed-version hint 3.0.0 is not published on npm for request,
and no published version >= 3.0.0 was found.
The advisory says the fix is request@3.0.0. That version was never published. This is why npm audit said "No fix available" - but it never told you the reason. One more command does:
cve-lite . --check-maintenance
| Severity | Rule | Package | Details |
|---|---|---|---|
| medium | DM001 | request@2.88.2 | Deprecated - last release 2020 (6 years ago) |
request was deprecated six years ago. It is never getting a 3.0.0. The "No fix available" dead end has a name and a real fix: stop upgrading request, replace it. No CVE scanner tells you that, because being unmaintained is not itself a CVE. (--check-maintenance also flags constraint drag - a direct dependency whose version range pins a vulnerable transitive below its fix - and CVE Lite CLI has a matching --check-overrides for overrides/resolutions that have rotted. See the Maintenance Risk and Override Hygiene guides.)
Severity stays honest, not inflated: a dependency whose range actively blocks a security fix is high; a merely-deprecated one is advisory medium, and release age is shown as context, never dressed up as a verdict - a stable, complete package that simply has not needed a release is left alone.
The point
npm audit, Dependabot, and the commercial scanners are all worth running. They answer "what is vulnerable?" - honestly, and often for free. But that is the easy question. The one that actually eats your afternoon is the next one - what do I run, and can I trust it? - and that is the whole reason CVE Lite CLI exists:
cve-lite . # validated, copy-run fixes - not just advisory IDs
cve-lite . --verbose # the versions-scanned proof behind every recommendation
cve-lite . --check-maintenance # the dead-end packages a CVE scan cannot explain
No other free tool brings this combination together: lockfile scanning across npm, pnpm, Yarn, and Bun, validated fix commands, parent-aware transitive guidance, and maintenance-risk detection - all in one OWASP Lab Project. (For a tool-by-tool breakdown against Snyk, npm audit, Trivy, and others, see the Comparison page.) It also gates CI (--fail-on, SARIF for Code Scanning), runs fully offline, and exports JSON, SARIF, and an interactive HTML report - see the CLI Reference.
It runs where the decision is actually made - in your terminal, before CI ever goes red - and it tells you what to run, not just what is wrong. It is free, open source, and built as an OWASP Lab Project specifically so that answer holds up to scrutiny.
npm install -g cve-lite-cli
git clone https://github.com/sonukapoor/acme-api.git && cd acme-api
cve-lite . --verbose
Scan. Understand. Fix.