# Does npm audit detect malicious packages?

> npm audit finds known vulnerabilities in legitimate packages. It is much weaker at finding deliberately malicious ones, and this explains why - plus what to run instead.

- Published: 2026-08-03
- Last updated: 2026-08-03

It is the reasonable assumption - you ran `npm audit`, it said "found 0 vulnerabilities", so your dependencies are fine. Unfortunately `npm audit` is answering a narrower question than most people think, and the gap is exactly where supply-chain attacks live.

## What npm audit actually checks

`npm audit` compares your dependency tree against the GitHub Advisory Database and reports entries that match. That database is overwhelmingly a record of **vulnerabilities** - accidental security bugs in legitimate, well-intentioned packages. A prototype pollution bug in a utility library, a ReDoS in a parser, a path traversal in a static file server.

That is genuinely useful, and you should keep running it. But a vulnerability is a mistake in code that is supposed to be there. A supply-chain attack is code that was never supposed to be there at all, and the two get handled very differently.

## Why malware slips through the gap

Three things work against you.

**Takedown removes the evidence.** When a malicious package is discovered, the registry usually removes or replaces it within hours. That is the right call for stopping the spread, but it means the package no longer exists to be looked up. Your lockfile still pins `evil-pkg@1.2.3`; the registry no longer has a record to match against; the audit comes back clean.

**Advisories lag, and sometimes never arrive.** A CWE-506 "embedded malicious code" advisory may be published days after the package was pulled, or not at all for smaller campaigns. Meanwhile the compromised version has been sitting in your lockfile the whole time.

**The damage is already done.** Most of these packages execute during `npm install` via a `postinstall` hook. By the time any tool tells you about it, the payload has already run with your environment variables in scope. Detection after the fact is about knowing what to rotate, not about prevention.

## What to run instead - or rather, as well

There is no single tool that covers this. A reasonable layered setup:

- **Keep `npm audit` in CI.** It catches real vulnerabilities and costs nothing.
- **Match your lockfile against known-malicious versions.** This is the specific gap above, and it is what this site does - we keep the compromised package–version pairs even after the registry has removed them, so a takedown does not erase your ability to check.
- **Disable install scripts where you can.** `npm config set ignore-scripts true` blocks the most common execution path. It breaks packages that genuinely need a build step, so it is easier to adopt in CI than locally.
- **Pin and commit your lockfile.** Without one, every fresh install re-resolves your ranges against whatever is on the registry today.
- **Keep install-time network egress narrow in CI.** Most payloads need to reach a C2 host to be useful.

## A worked example

Take a typosquat published against a popular HTTP client. The sequence usually runs:

1. Attacker publishes `ax1os@1.0.0` with a `postinstall` script.
2. Someone typos it, or an LLM-generated snippet suggests it, and it lands in a lockfile.
3. `npm install` runs the hook; environment variables are exfiltrated.
4. A researcher reports it; npm removes the package within a few hours.
5. You run `npm audit` the following week. Nothing to report - the package is gone.

Steps 3 and 5 are the whole problem. The compromise is real and still pinned in your lockfile, but the lookup that would have found it no longer resolves.

## Frequently asked questions

### Is `npm audit` worth running at all?

Yes. It is good at what it does - finding known vulnerabilities in legitimate packages - and that is a real category of risk. The mistake is reading "0 vulnerabilities" as "no malicious code", which is a different claim it was never making.

### Do `yarn audit` and `pnpm audit` behave differently?

No, in the way that matters. They query advisory data for known vulnerabilities and inherit the same blind spot around removed malicious packages.

### Would Dependabot or Renovate have caught it?

They keep you on current versions, which genuinely reduces exposure to old vulnerable releases. But they are driven by the same advisory data, and automated upgrades can move you *onto* a compromised release if a maintainer account has just been taken over.

## Next step

Check your package-lock.json: https://dependencywatch.io/check/package-lock-json

## Related guides

- [You installed a malicious package. What now?](https://dependencywatch.io/guides/what-to-do-after-installing-a-malicious-package) - A practical incident-response order of operations for developers who have just found a compromised package in their dependency tree - what to rotate, in what order, and what not to bother with.
- [How to tell if an npm package is malicious](https://dependencywatch.io/guides/how-to-tell-if-an-npm-package-is-malicious) - Practical signals for judging whether an npm package is safe to install - what actually predicts trouble, what looks alarming but does not, and how to check before you install.

---

Canonical page: https://dependencywatch.io/guides/does-npm-audit-detect-malware
Markdown version: https://dependencywatch.io/guides/does-npm-audit-detect-malware.md
Site index for agents: https://dependencywatch.io/llms.txt
DependencyWatch.io is operated by Precursor Security (https://precursorsecurity.com).
