Last month, a team spent three days patching 47 npm audit findings. Two of them actually mattered.
The other 45 were textbook alert fatigue. A CVSS 8.2 vulnerability in a nested dependency that their application never calls. A CVSS 7.1 flaw affecting only a code path behind three layers of permission checks. These deserve attention someday, but not at emergency priority.
Meanwhile, a CVSS 4.0 vulnerability in their authentication middleware went unpatched for two weeks because npm audit flagged it as "Low." No one was prioritizing below "High."
That CVSS 4.0 was being actively exploited in the wild.
TL;DR: npm audit ranks vulnerabilities by CVSS severity, which measures theoretical impact — not likelihood of exploitation. To cut alert fatigue and patch what matters first, you need two additional signals: EPSS (probability of exploitation in the next 30 days) and CISA KEV (confirmed active exploitation right now). This post shows how to use both.
What We'll Cover
- What npm audit actually does (and doesn't do)
- The alert fatigue funnel: 47 findings → 2 that matter
- Why CVSS alone fails for npm
- Real package examples with EPSS + KEV data
- Decision tree: how to prioritize npm findings
- Side-by-side: npm audit vs GeekWala output
- Building a workflow that scales
npm audit gives you severity ratings, not risk rankings. CVSS scores are useful for understanding vulnerability characteristics, but they're terrible at answering the question that actually matters: "Which vulnerabilities should my team patch first?" The answer requires two additional signals that npm audit doesn't provide: EPSS (exploit probability) and CISA KEV (active exploitation).
What npm audit Actually Does
When you run npm audit, the tool:
- Parses your
package-lock.jsonornpm-shrinkwrap.json - Queries the npm Security Advisory database (synchronized with NVD and GitHub Security Advisory)
- Matches installed versions against known vulnerable versions
- Returns a report with severity levels: critical, high, moderate, low
These severity levels come directly from CVSS v3.1 scores. The mapping is simple but rigid:
CVSS 9.0–10.0 → Critical
CVSS 7.0–8.9 → High
CVSS 4.0–6.9 → Moderate
CVSS 0.1–3.9 → Low
The output feels authoritative: "41 vulnerabilities found, 7 high, 34 moderate." Your team springs into action, patches the high ones, schedules the moderate ones, ignores the low ones.
You've just prioritized by noise instead of by signal.
The Alert Fatigue Funnel
Here's what happens when a typical Node.js project runs npm audit:
npm audit output: 47 vulnerabilities
│
├── 31 × Low severity (EPSS avg 0.02 — practically zero exploitation risk)
│
├── 12 × Moderate severity (EPSS avg 0.05 — unlikely to be exploited)
│
├── 3 × High severity (EPSS avg 0.18 — monitor closely)
│ ├── lodash prototype pollution EPSS 0.09 KEV: ✗ → routine maintenance
│ ├── minimatch ReDoS EPSS 0.04 KEV: ✗ → patch next sprint
│ └── express path traversal EPSS 0.68 KEV: ✓ → PATCH TODAY ◀
│
└── 1 × Critical severity (EPSS avg 0.31 — check individually)
└── node-fetch SSRF EPSS 0.12 KEV: ✗ → patch within 7 days
Result after EPSS + KEV filtering:
47 alerts → 2 require immediate action → 45 can wait
47 findings. 2 that actually matter. npm audit can't tell you which 2 — it only sees the raw count. You need EPSS and CISA KEV to identify the ones that need emergency action.
Why CVSS Alone Fails for npm
CVSS measures theoretical severity — how bad a vulnerability could be if exploited. It doesn't measure whether anyone is trying to exploit it. npm audit maps CVSS ranges directly to severity labels (Critical ≥ 9.0, High ≥ 7.0, Moderate ≥ 4.0, Low < 4.0), so your team's priorities are driven entirely by a score that ignores real-world threat activity.
The two signals npm audit is missing:
EPSS (Exploit Prediction Scoring System) — a machine-learning model by FIRST.org that predicts the probability a CVE will be exploited in the next 30 days. Unlike CVSS, EPSS evolves as new threat intelligence, proof-of-concept code, and malware analysis arrive.
CISA KEV (Known Exploited Vulnerabilities) — a curated catalog of vulnerabilities that CISA has confirmed are being actively exploited right now. If a CVE is on KEV, it's not theoretical — threat actors are using it in live attacks.
How npm audit Gets Real Packages Wrong
Let's look at three npm packages your project probably depends on, and how npm audit's CVSS-only view misleads you:
| Package | CVE | npm audit Says | CVSS | EPSS | KEV | What You Should Actually Do |
|---|---|---|---|---|---|---|
| lodash < 4.17.21 | Prototype Pollution | HIGH — patch urgently | 7.2 | 0.02 | No | Patch next quarter. EPSS 0.02 = almost nobody exploiting this. |
| express < 4.17.1 | Path Traversal | HIGH — same urgency as lodash | 7.8 | 0.68 | Yes | Patch TODAY. KEV entry + EPSS 0.68 = actively weaponized. |
| minimatch < 3.0.5 | ReDoS | MODERATE — schedule later | 5.3 | 0.04 | No | Correct call, but for the wrong reason. |
npm audit gives lodash and express identical urgency. In reality, express is a five-alarm fire and lodash is routine maintenance. CVSS can't distinguish between them.
Decision Tree: Prioritizing npm Vulnerabilities
Instead of sorting by CVSS severity, use this npm-specific decision tree:
npm audit finding
│
▼
┌─ Is it in a production dependency (not devDependency)?
│ ├─ NO → Log it, fix in your next dependency update
│ └─ YES ↓
│
├─ Is it on CISA KEV?
│ ├─ YES → 🔴 PATCH WITHIN 24 HOURS
│ │ Run: npm audit fix or manually bump version
│ └─ NO ↓
│
├─ What's the EPSS score?
│ ├─ > 0.7 → 🟠 Patch this week
│ ├─ 0.3–0.7 → 🟡 Include in next sprint
│ └─ < 0.3 → 🟢 Patch in normal dependency update cycle
│
└─ Tiebreaker: Higher CVSS goes first when EPSS scores are equal
Notice: CVSS only appears as a tiebreaker. The primary sort is KEV status, then EPSS. This is fundamentally different from how npm audit ranks findings.
Side-by-Side: npm audit Output vs GeekWala
What your terminal shows you today:
$ npm audit
high │ Lodash Prototype Pollution │ lodash <4.17.21
high │ Express Path Traversal │ express <4.17.1
moderate│ minimatch ReDoS │ minimatch <3.0.5
3 vulnerabilities (1 moderate, 2 high)
What you see after scanning the same package-lock.json with GeekWala:
┌──────────┬──────────┬───────┬──────┬─────────────────┐
│ Package │ CVE │ CVSS │ EPSS │ KEV Status │
├──────────┼──────────┼───────┼──────┼─────────────────┤
│ express │ CVE-2024 │ 7.8 │ 0.68 │ 🔴 ACTIVE │
│ │ -29041 │ │ │ Added 2024-10-15│
├──────────┼──────────┼───────┼──────┼─────────────────┤
│ lodash │ CVE-2020 │ 7.2 │ 0.02 │ — │
│ │ -8203 │ │ │ │
├──────────┼──────────┼───────┼──────┼─────────────────┤
│ minimatch│ CVE-2022 │ 5.3 │ 0.04 │ — │
│ │ -3517 │ │ │ │
└──────────┴──────────┴───────┴──────┴─────────────────┘
Sorted by: KEV status, then EPSS descending
Action: 1 requires immediate patching, 2 routine
Same three findings. Completely different prioritization. npm audit treats lodash and express with equal urgency. GeekWala puts express at the top because it's actively weaponized (KEV entry) with a 68% exploitation probability (EPSS 0.68). Lodash and minimatch drop to routine maintenance.
See how your npm findings look with EPSS + KEV enrichment.
Scan your package-lock.json → — get the same side-by-side view above for your own dependencies in under a minute. No account needed.
Building an npm Security Workflow That Scales
npm audit is useful during development — it catches obvious issues with zero setup. But for production projects with hundreds of dependencies, you need enrichment on top:
Local Development CI/CD Pipeline Production
───────────────── ────────────── ──────────
npm audit GeekWala API scan Scheduled GeekWala scans
(quick sanity check) (fail build if (daily or weekly)
EPSS > 0.8 or KEV)
│ │ │
└──── All feed into ──────┴────────────────────────┘
│
GeekWala Dashboard
(historical trends, team view,
webhook alerts on EPSS spikes)
The practical steps:
- Keep
npm auditin your pre-commit hooks for fast feedback during development - Scan your package-lock.json with GeekWala in CI — gate deploys on KEV or high-EPSS findings
- Run scheduled scans on production lock files to catch EPSS score changes after deploy
- Subscribe to webhook alerts so your team hears about EPSS spikes before they become KEV entries
Frequently Asked Questions
Can I use npm audit and still get EPSS/KEV signals?
Not from npm audit itself — it only provides CVEs and CVSS scores. You'd need to manually cross-reference FIRST.org for EPSS and the CISA KEV catalog for active exploitation data. GeekWala automates this by enriching every CVE with both signals when you scan your package-lock.json.
Does this work for monorepos with multiple package-lock.json files?
GeekWala scans individual package-lock.json files. For monorepos with npm workspaces, upload the root lock file — it includes all workspace dependencies. For monorepos with independent lock files per package, scan each one separately. Full monorepo workspace support with unified reporting is coming in 2026.
My vulnerable dependency is transitive (deeply nested). How do I trace it?
npm's dependency tree can bury vulnerable packages 5+ levels deep. Run npm ls <package> to see the dependency chain. When you scan with GeekWala, the results show the full path: your-app → parent-pkg → child-pkg → vulnerable-pkg. This helps you decide whether to bump the direct parent (preferred) or use npm audit fix --force (riskier, may introduce breaking changes).
Should I use npm audit fix --force when a KEV vulnerability is found?
Use npm audit fix (without --force) first — it upgrades within semver ranges and is generally safe. --force can introduce major version bumps that break your application. For KEV entries that npm audit fix can't resolve, manually bump the vulnerable package or its parent in package.json, then test thoroughly. The urgency of KEV doesn't justify shipping broken code.
How do EPSS scores interact with npm's severity levels?
They don't — that's the problem. npm audit maps CVSS ranges to severity labels (critical/high/moderate/low) and ignores exploitation probability entirely. A "moderate" npm finding could have EPSS 0.9 (almost certainly being exploited) while a "critical" finding has EPSS 0.01 (nobody's touching it). For a deeper explanation of how EPSS works and how to read the scores, see What is EPSS?.
Stop triaging by CVSS severity. Start patching by exploitation probability.
See which of your npm findings are actually being exploited → — upload your package-lock.json and get results sorted by KEV status and EPSS in under a minute. No account needed.


