Auditing and overriding dependencies

npm · Advanced · 12 min

Most vulnerabilities live in transitive dependencies you never chose directly.

npm audit sends your dependency tree to the registry's advisory database and lists known vulnerabilities with severity, the vulnerable range and the dependency path. npm install prints a summary automatically.

Fixing, in order of preference:

  • npm audit fix: upgrades within your declared ranges. Safe to run.
  • Upgrade the direct dependency that pulls in the vulnerable package (use npm explain <pkg> to find it).
  • npm audit fix --force may install breaking major versions. Review its plan, never run it blindly in CI.
  • overrides: in the root package.json, force a version anywhere in the tree, or only under one parent:
"overrides": { "semver": "^7.5.4", "jest": { "micromatch": "^4.0.8" } }

Overrides only work in the root project (not in published packages). Use $name to reference your own direct dependency's version and keep them in sync. Remove overrides once upstream fixes land.

Triage matters: an advisory in a dev-only build tool that never sees untrusted input is lower risk than one in your HTTP parser. Use npm audit --omit=dev to focus on what ships, and --audit-level=high in CI to fail only above a threshold.

npm audit signatures verifies registry signatures and provenance attestations of installed packages.

Example

npm audit
# semver  <7.5.2
# Severity: moderate
# semver vulnerable to Regular Expression Denial of Service
# fix available via `npm audit fix`
# node_modules/old-lib/node_modules/semver
#   old-lib  *  Depends on vulnerable versions of semver

npm audit fix                       # in-range upgrades only
npm explain semver                  # who depends on it?
npm audit --omit=dev --audit-level=high   # CI gate on shipped code

# package.json: force a patched version for all or one subtree
#   "overrides": {
#     "semver": "^7.6.0",
#     "old-lib": { "semver": "^7.6.0" }
#   }
npm install && npm ls semver        # verify every copy is patched
npm audit signatures                # verify registry signatures/provenance

Remember

  • npm audit fix stays in range; --force can break things
  • Upgrade the direct parent first, overrides as a last resort
  • Overrides only work in the root package.json
  • Gate CI on shipped code with --omit=dev --audit-level

Watch out for

  • Running npm audit fix --force in CI and shipping surprise major upgrades.

Check yourself

  1. A vulnerable transitive package is pinned by an unmaintained parent. Which tool forces a patched version?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.npmjs.com/cli/v11/commands/npm-audit