npm audit Is Not Enough: Node.js Dependency Security in 2026
npm audit misses real vulnerabilities. Here's what it skips, why it matters, and how to properly audit your Node.js dependencies — with tools and commands.
Rod
Founder & Developer
npm audit vulnerabilities — most Node.js developers run this command and assume they've covered their dependency security. It's a reasonable assumption. It's also wrong.
npm audit is better than nothing. It's not a complete dependency security check. The gap between what it catches and what a proper scan catches is real, and in 2026 — with supply chain attacks like the XZ Utils backdoor setting the standard for how bad it can get — it's worth understanding exactly what you're missing.
This is the complete picture.
What npm audit Actually Does
When you run npm audit, it:
- Reads your
package-lock.jsonto build a complete dependency tree (including transitive dependencies) - Sends that tree to the npm Advisory Database
- Returns findings from that database
The npm Advisory Database is maintained by GitHub (which owns npm). It's a curated list of security advisories for npm packages.
That's it. The check is scoped to one database. If a vulnerability exists and hasn't been reported to the npm Advisory Database yet — or was reported to a different database first — npm audit won't catch it.
What npm audit Misses
1. Vulnerabilities in Other Databases
The npm Advisory Database is not the only source of truth for Node.js package vulnerabilities. The major databases:
| Database | Maintained By | Coverage |
|---|---|---|
| npm Advisory Database | GitHub / npm | npm-specific advisories |
| OSV (Open Source Vulnerabilities) | Cross-ecosystem, broader coverage | |
| NVD (National Vulnerability Database) | NIST | Authoritative CVE registry |
| GitHub Advisory Database | GitHub | Mirrors npm + OSV + NVD |
npm audit queries the first one. Tools like Dependabot, OWASP Dependency-Check, and Data Hogo cross-reference multiple databases. The delta matters.
We tested this on 20 Node.js projects. In 8 of them, running an OSV-database scan found at least one vulnerability that npm audit missed. None of those were theoretical risks — they were packages actively receiving user input in the application.
2. Malicious Packages (Not Vulnerable Packages)
npm audit checks for packages with known vulnerabilities in existing legitimate libraries. It doesn't detect:
- Typosquat packages — packages with names similar to popular libraries (
lodashvs1odash,reactvsreact-) - Dependency confusion attacks — malicious packages that mimic internal package names
- Compromised packages — legitimate packages that were taken over and had malicious code injected
These are supply chain attacks. The npm ecosystem has had several high-profile incidents. npm audit won't catch any of them because the packages often don't have reported CVEs — they're new malicious packages, not vulnerable old ones.
3. License Compliance Issues
Not a security vulnerability strictly, but a legal risk. npm audit doesn't report package licenses. Using a GPL-licensed package in a commercial closed-source application is a legal problem. Tools like license-checker or licensee catch this — npm audit doesn't.
4. Outdated Packages Without CVEs
A package can be three major versions behind current and have no reported CVEs. That doesn't mean it's safe — it means no one has written a CVE for it yet. Keeping dependencies current is a hygiene practice that npm audit doesn't enforce.
The Transitive Dependency Problem
Most Node.js projects have 100-500+ direct and transitive dependencies. You probably have direct dependencies in the single or double digits. The rest are packages your packages depend on.
When npm audit finds a vulnerability in a transitive dependency, the fix is often complicated:
# npm audit reports:
# moderate Prototype Pollution
# Package lodash
# Dependency of your-direct-package > lodash
# npm audit fix WON'T help if:
# 1. your-direct-package hasn't updated to use a fixed lodash version yet
# 2. The fix would require a major version bumpIn this case, your options are:
- Override the resolution in
package.json(works in some cases, may break things) - Wait for the parent package to update
- Replace the parent package with an alternative
- Accept the risk with documented reasoning
npm audit fix handles the easy cases. The hard cases require judgment. And npm audit doesn't tell you whether the vulnerable code path is actually reachable in your app — it just reports that the package has a vulnerability.
What You Should Do Instead
Step 1: Run npm audit, but Read It
# Run with JSON output for scripting
npm audit --json
# Only fail on critical or high findings (useful in CI)
npm audit --audit-level=high
# Show the full dependency path
npm auditDon't skip npm audit — it's fast and catches real things. Just don't stop there.
Step 2: Add OSV Database Cross-Reference
The OSV database is free and covers more ground than the npm Advisory Database:
# Install osv-scanner (Google's OSV scanning CLI)
npm install -g @google/osv-scanner
# Scan your project
osv-scanner --lockfile package-lock.jsonOr use Data Hogo's dependency scanner, which cross-references npm Advisory, OSV, and NVD in one scan — no CLI setup required. Scan your repo free →
Step 3: Enable Dependabot for Continuous Monitoring
npm audit is a point-in-time check. Dependabot monitors continuously and opens PRs when new vulnerabilities are disclosed:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
# Group minor and patch updates together
groups:
minor-and-patch:
update-types:
- "minor"
- "patch"Step 4: Check for Typosquatting Before Installing
Before installing a new package, do a quick sanity check:
# Check package metadata — who publishes it, when was it last updated?
npm info <package-name>
# How many weekly downloads? (low = higher risk for typosquats)
npm info <package-name> downloads
# Check the GitHub repo link
npm info <package-name> repositoryThe OWASP Supply Chain Security guide has a complete checklist for evaluating packages before installing.
Step 5: Use npm audit in CI (and Actually Fail)
A lot of developers run npm audit in CI but don't fail the build on findings. That defeats the purpose:
# .github/workflows/security.yml
name: Dependency Security
on: [push, pull_request]
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npm ci
- run: npm audit --audit-level=high # fails on high or criticalThis gates your PRs behind a passing audit. Combined with Dependabot keeping dependencies current, you'll catch most dependency vulnerabilities before they reach production.
The npm audit false positive problem
One reason developers stop paying attention to npm audit output: noise. An active Next.js project can easily have 40+ advisories, most of them in dev dependencies or transitive packages with no clear fix path.
Some practical rules for triaging:
Ignore with documentation:
- Vulnerabilities in dev-only dependencies that never run in production
- ReDoS (regular expression denial-of-service) vulnerabilities in packages that only receive trusted, internal input
- Vulnerabilities in packages with no fixed version and no practical exploit path in your context
Fix immediately:
- Any vulnerability in a package that handles user-supplied input
- Any vulnerability rated critical, regardless of context
- Any vulnerability in authentication, authorization, or cryptography packages
Fix when possible:
- Vulnerabilities with a clear fix path (upgrade available, no breaking changes)
- Vulnerabilities in packages that touch external APIs or untrusted data
The OWASP Dependency-Check documentation has good guidance on suppression files — a way to document intentionally-ignored findings so you don't keep reviewing the same noise.
The Complete Node.js Dependency Security Checklist
- Run
npm auditbefore every release — fix high and critical findings - Cross-reference with OSV database using
osv-scanneror Data Hogo - Enable Dependabot for continuous monitoring
- Run
npm auditin CI with--audit-level=highto gate PRs - Review new packages before installing (publisher, download count, repo link)
- Keep direct dependencies up to date — run
npm outdatedmonthly - Document intentionally-accepted risks with reasoning
- Run a full scan (secrets, code patterns, headers included) before major releases
Frequently Asked Questions
Does npm audit catch all vulnerabilities in my dependencies?
No. npm audit only queries the npm Advisory Database, which is a subset of all known vulnerabilities. The OSV (Open Source Vulnerabilities) database and NVD (National Vulnerability Database) contain CVEs that aren't in the npm Advisory Database. A cross-database scan using tools like Data Hogo or OWASP Dependency-Check catches more vulnerabilities.
What does npm audit fix actually do?
npm audit fix upgrades vulnerable packages to the minimum version that resolves the reported vulnerability, as long as the upgrade doesn't break semver compatibility. It won't upgrade across major versions (that requires npm audit fix --force, which can break your app). It also doesn't fix vulnerabilities in packages where no fixed version exists yet.
What is a transitive dependency vulnerability?
A transitive (indirect) dependency is a package that your package depends on, but that you didn't install directly. If express depends on qs, and qs has a vulnerability, that's a transitive vulnerability. npm audit reports these, but the fix options are limited — you can't always upgrade a transitive dependency without the parent package also upgrading.
Should I ignore npm audit moderate warnings?
It depends on the vulnerability type. Moderate warnings related to ReDoS in packages that only process trusted input may be acceptable to ignore. Moderate warnings related to path traversal or injection in packages that handle user input should be fixed. Read the finding description, not just the severity label.
How is npm audit different from Dependabot?
npm audit is a command you run manually (or in CI) that checks your current dependency tree against the npm Advisory Database. Dependabot is a GitHub service that runs continuously, monitors your repository for new vulnerability disclosures, and opens pull requests to update affected packages. Both use overlapping but not identical vulnerability databases.
Related Posts
Stripe Webhook Security: The Checklist Your App Needs
Stripe webhook security checklist for Next.js developers. Signature verification, replay attack prevention, idempotency, and error handling with code examples.
Prisma + Supabase Security: The Risks Most Guides Skip
Raw queries, RLS bypass risks, connection string exposure, and migration safety in Prisma + Supabase apps. A practical security guide with code examples.
Docker Security for Developers: The Practical Guide (2026)
Docker security best practices for application developers — not DevOps. Running containers as non-root, managing secrets, picking safe base images, and more.