← Alle Neuigkeiten
dependency-hygiene5 Min. Lesezeit

What npm audit won't tell you about your dependency tree

Von Seaworthy · 31. Juli 2026

A rusted padlock hanging on a chain-link gate

Photo by Meritt Thomas on Unsplash

You ran npm audit. It came back clean. Zero vulnerabilities. Nice green checkmark, ship it.

Except "0 vulnerabilities" is a claim about one specific database, not a claim about your code. npm audit (and pip audit, and cargo audit, and every tool in that family) checks your dependency tree against a list of known, disclosed CVEs. That's it. That's the whole trick. It's a lookup, not an analysis. If nobody has filed a CVE for a problem yet, or if the problem never gets a CVE because it's a supply chain compromise rather than a bug, the audit has nothing to say about it.

That distinction matters more than most teams treat it.

What the audit database actually contains

npm audit pulls from the GitHub Advisory Database. pip audit pulls from the Python Packaging Advisory Database (also mirrored via OSV). These are good projects, staffed by people who genuinely try to catch everything. But they're reactive by construction. A vulnerability gets in only after someone finds it, reports it, and a maintainer or a security researcher writes it up. There's a lag between "this package has a real problem" and "this package has a filed advisory", and during that lag your audit is silent.

Sometimes the lag is days. Sometimes it's years. The event-stream incident from 2018 is the standard example: a malicious actor got commit access to a popular package by volunteering to help maintain it, then quietly added a dependency that stole Bitcoin wallet credentials from downstream apps. It ran in production for months before anyone noticed, because there was no CVE to catch, only a git commit that looked ordinary. An audit tool checking against a disclosure database would have shown zero vulnerabilities the entire time, because there was nothing to disclose yet.

Transitive dependencies you never chose

The dependency you actually typed into package.json is the one you reviewed, maybe. The forty packages it pulled in underneath it are the ones nobody reviewed, and some of those get resolved in ways you wouldn't expect.

Version ranges are the obvious case. You pin ^2.1.0, npm resolves to 2.4.7 next Tuesday because that's what satisfies the range, and you never see a diff. Lockfiles help here, genuinely, use them and commit them. But lockfiles only freeze what's already resolved. They don't stop a fresh npm install in CI from picking up a new transitive version if the lockfile itself gets regenerated, and they don't protect you from optional dependencies, peer dependencies pulled in by a plugin system, or packages fetched at build time by a bundler plugin rather than declared anywhere in your manifest. Postinstall scripts are their own category of blind spot: a package can run arbitrary code on your machine or your CI runner during install, before npm audit has even had a chance to think about it.

Check how deep your tree actually goes before you assume you know what's in it:

# see the full resolved tree, not just what you declared
npm ls --all

# find who actually pulls in a package you didn't expect
npm why left-pad

# same idea for Python
pip show some-package
pipdeptree --reverse --packages some-package

If you've never run npm ls --all on a real project, do it once. The size of the output is the point.

No CVE for "the maintainer's account got hijacked"

This is the one audit tools structurally can't catch, and it's becoming the more common attack, not the rarer one. A maintainer's npm token leaks, or their email gets taken over, or they get socially engineered into adding a co-maintainer who turns out to be hostile. A new version gets published that looks like a routine patch bump. It has a plausible changelog. It passes whatever automated checks the registry runs. And it ships with a payload, credential exfiltration, a crypto miner, a backdoor, whatever the attacker's incentive happens to be that month.

There have been enough of these (ua-parser-js, coa, rc, various colors/faker incidents, the more recent wave hitting popular CI-adjacent packages) that "supply chain compromise" is now a specific, well-understood attack category, not a hypothetical. None of them show up in an audit at the moment they ship, because at that moment there's no advisory. The CVE, if one ever gets filed, comes after someone notices the behavior, which can be weeks later, after thousands of installs.

What to actually do about it

Running the audit command is still worth doing. Just stop treating it as a security control and start treating it as one input among several.

  • Pin exact versions for anything that touches money, auth, or infrastructure, and bump deliberately with a diff review, not automatically.
  • Turn on Dependabot or Renovate, but read the diffs it opens instead of auto-merging everything green. A patch bump from a compromised account looks exactly like a normal patch bump.
  • Use npm ci in CI and deployment, never npm install, so builds use the exact locked tree instead of re-resolving anything.
  • Restrict or audit postinstall scripts. npm config set ignore-scripts true is aggressive but forces you to know which packages actually need install-time execution, which is usually far fewer than you'd think.
  • Watch for maintainer churn on packages you depend on heavily. A sudden new co-maintainer on a package with millions of weekly downloads is worth five minutes of attention.
  • Treat "0 vulnerabilities" as "0 known, disclosed vulnerabilities as of this morning," say that sentence to yourself, and move on with appropriate skepticism rather than false comfort.

None of this replaces the audit command. It just puts it in its place: a floor, not a ceiling.

Seaworthy's dependency hygiene checks flag known CVEs in your dependency tree the same way npm audit and pip audit do, as one signal in a broader scan, not as proof the tree is clean.

Dieser Artikel wurde von KI generiert und fasst öffentlich verfügbare Quellen zusammen.

Von den Machern von Seaworthy

Seaworthy scannt dein Repository nach den Problemen, die in Artikeln wie diesem behandelt werden.

Sicherheitslücken, offengelegte Geheimnisse und Fehlkonfigurationen — erkannt, bevor du bereitstellst. Kostenlos, kein Konto nötig.

$ npx seaworthycode