Article · Vulnerability scanning
Why npm & pnpm audit miss vulnerabilities
npm audit and pnpm audit are a reasonable first
check — but a clean audit is one of the most misread signals in
JavaScript security. It doesn’t mean your dependencies are safe; it means
one advisory source, reachable at one moment, found nothing in the view of
your tree it was handed. Understanding how audit actually
works explains exactly where it falls short — and what more
complete scanning looks like.
Updated 26 Jul 2026 · by the depproof team
What audit actually does
It helps to know there’s no local analysis happening. When you run
npm audit or pnpm audit, the client sends a
description of your resolved dependency tree to your configured
registry’s audit endpoint, and prints the advisories that
come back. That advisory data traces to the
GitHub Advisory Database, which curates known
vulnerabilities for the npm ecosystem. In other words:
audit is a network request to a service, not a scanner
with its own database reasoning over your code.
That single design fact explains almost every way audit lets teams down.
The four structural reasons it misses things
- 1. It’s only as broad as one source. Audit reflects the GitHub Advisory Database for npm. A vulnerability that hasn’t been recorded there yet — or that lives in a different database — won’t appear, no matter how carefully you run it.
- 2. No network, no results — silently. Because it depends on a reachable audit endpoint, a private registry that doesn’t implement one, an air-gapped runner, or a blocking proxy can turn audit into a command that returns nothing — which reads like “all clear” but means “didn’t actually check.” That failure mode isn’t unique to audit: an empty scan result is ambiguous by nature.
- 3. It’s npm-ecosystem only. Audit sees your JavaScript dependencies and nothing else. A repo that also ships Java, Go, or containers needs separate tooling — audit gives no signal there.
- 4. Presence, not reachability — and no inventory. Audit reports that a vulnerable version is present; it can’t tell you whether the vulnerable code path is actually used, and it doesn’t leave you a machine-readable component inventory (an SBOM) to reason about later. You get a console dump, not an artifact.
Why npm audit and pnpm audit disagree
Teams are often unsettled to find npm audit clean while
pnpm audit flags issues, or vice versa. Both hit a registry
endpoint backed by the same advisory data, so the difference comes from
what they ask about: how each resolves and deduplicates the tree,
whether devDependencies are included, and the exact state of
the advisory data at the moment of the call. Different views of the tree,
and different timing, yield different counts. The lesson isn’t “trust the
stricter one” — it’s that a single audit number is a fragile
measure of dependency risk.
What more complete scanning looks like
None of this makes audit useless — it makes it a
floor. A more dependable approach fixes the structural gaps
directly:
- Read the lockfile, not a service. Resolving
pnpm-lock.yaml/package-lock.jsonlocally means the scan works behind a private registry, a mirror or a proxy — no audit endpoint required. - Check open, aggregated advisory data. OSV pulls from many sources (including GitHub Advisories and OpenSSF malicious-package data) and is built to be queried directly against a lockfile — broader than a single source, and portable rather than proprietary.
- Produce an inventory. Emitting a CycloneDX SBOM alongside the findings gives you something durable to re-check when the next advisory drops — the difference between a one-off console dump and continuous coverage.
The point isn’t a specific tool — it’s the shape: lockfile-based, open advisory data, full transitive tree, real artifact. That shape removes the network dependency, the single-source blind spot, and the “no inventory” gap in one move.
Frequently asked questions
How does npm audit (and pnpm audit) actually work?
When you run npm audit or pnpm audit, the client sends a description of your resolved dependency tree to your configured registry’s audit endpoint and displays the advisories that come back. That advisory data traces to the GitHub Advisory Database, which curates the npm ecosystem’s known vulnerabilities. The key point is that audit is a network request to a service — it isn’t analyzing your code or maintaining a local vulnerability database.
Does a clean npm/pnpm audit mean my dependencies are safe?
No. A clean audit means one advisory source, reachable at one moment, found nothing for the view of the tree it was given. It can miss vulnerabilities that aren’t in the GitHub Advisory Database yet, return nothing when the audit endpoint is unreachable (a private registry, air-gapped CI, or a proxy), and it says nothing about whether a vulnerable code path is actually used. Treat a clean audit as one signal, not a guarantee.
Why do npm audit and pnpm audit give different results?
Both hit a registry audit endpoint backed by the same advisory data, but they can differ in how they resolve and deduplicate the dependency tree, which dependencies they include (production-only versus including devDependencies), and the exact state of the advisory data at the moment of each call. Different views of the tree, and different timing, produce different result counts — which is why one can look clean while the other flags issues.
What is the difference between npm audit and OSV-based scanning?
npm audit relies on a registry audit endpoint and the GitHub Advisory Database for the npm ecosystem. OSV (osv.dev) is an open, aggregated vulnerability database that pulls from many sources — including GitHub Advisories and OpenSSF malicious-package data — and is designed to be queried by tools directly against a lockfile. Scanning a lockfile against OSV doesn’t need a registry audit endpoint, works offline or self-hosted, and draws on a broader set of advisory sources.
How can I scan dependencies for vulnerabilities more completely?
Use a scanner that reads your lockfile directly (so it works without a registry audit endpoint, offline, or behind a private registry), checks against open aggregated advisory data like OSV, resolves the full transitive tree, and produces a machine-readable inventory (an SBOM) alongside the findings. That combination addresses the network dependency, the single-source coverage gap, and the “no inventory” limitation of the built-in audit commands at once.
Keep reading
- pnpm audit not working? Causes & fixes — the practical troubleshooting version of this article.
- Scan npm dependencies for vulnerabilities — a lockfile-based, self-hosted scan you can gate CI on.
- Zero findings is not zero risk — the four input problems that make any scanner, not just audit, report a confidently empty result.
- OSV vs CVE for dependency scanning — why package-keyed advisory data matches a lockfile and CVE/CPE data can’t.
- The part that never finishes — why the count moves on code nobody touched, and the cadence that keeps up.
- Dependency governance — turning per-repo scans into one org-wide, compliance-ready answer.
General information for engineering teams. depproof is not affiliated with npm, pnpm, GitHub, or Snyk; product names are used nominatively.