← Blog
·8 min read

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:

  1. Reads your package-lock.json to build a complete dependency tree (including transitive dependencies)
  2. Sends that tree to the npm Advisory Database
  3. 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) Google 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 (lodash vs 1odash, react vs react-)
  • 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 bump

In 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 audit

Don'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.json

Or 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> repository

The 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 critical

This 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 audit before every release — fix high and critical findings
  • Cross-reference with OSV database using osv-scanner or Data Hogo
  • Enable Dependabot for continuous monitoring
  • Run npm audit in CI with --audit-level=high to gate PRs
  • Review new packages before installing (publisher, download count, repo link)
  • Keep direct dependencies up to date — run npm outdated monthly
  • 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.

npmnode.jsdependency scanningsecurityjavascriptSCApackage securityvibe-coding