Because npm audit works from your dependency tree. It sends package names and versions to the registry and asks for known vulnerabilities, using your lockfile. A script tag pointing at a CDN URL, or a library copied into a folder, is not in that tree, so it is never checked.
What npm audit does
Per the npm docs, the command submits a description of your dependencies to your registry and requests a report of known vulnerabilities, then calculates impact and remediation. By default it needs a package-lock or shrinkwrap file. Its input is the tree.
That is a good tool for what it covers. The point here is its boundary.
What sits outside the boundary
| Item | In the lockfile? | Seen by npm audit? |
|---|---|---|
| Package installed with npm and bundled | Yes | Yes |
| Library loaded with a script tag from a CDN | No | No |
| File copied into a vendor or public folder | No | No |
| Snippet pasted from documentation | No | No |
| Vendor tag or analytics script | No | No |
| Package installed globally on a build machine | No | No |
If your page loads an old library from a URL, a clean audit result says nothing about it.
How to close the gap
- Find them. Use your script inventory and a search of templates for src URLs.
- Bring libraries into npm. Install the same version as a dependency and bundle it. The audit then sees it, and the version becomes visible in your lockfile.
- Pin what stays remote. Use exact versions with an integrity hash. See is a floating version in a CDN URL safe.
- Scan deployed pages. A scan of the live site can recognize old library signatures that no manifest declares.
- Record the rest in your SBOM as components and services, see should a web app SBOM list CDN scripts.
- Set a review date for every remaining remote script.
Other limits worth knowing
- The docs say some vulnerabilities cannot be fixed automatically and need manual review.
- npm audit fix can go outside your stated version range only with the force option, including major version changes.
- The omit option leaves dependency types out of the audit. By default omit is dev when NODE_ENV is production, so check the flags your CI uses.
- npm audit signatures is a separate command that verifies registry signatures and provenance. It is not part of the vulnerability check.
Make the result mean something
When you report to leadership or a customer that you audit dependencies, say what is included. "We audit all npm packages in the lockfile, and track URL loaded scripts in a separate inventory" is truthful and useful. "We have no known vulnerabilities" after a clean npm audit is not.
Safeguard's SBOM and dependency scanning cover your repositories, and you can start with a free scan at gold.safeguard.sh/scan.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how findings are tracked from detection to resolution.
Quick check
Does a clean npm audit mean my site is free of vulnerable libraries?
No. It covers the dependency tree only. Vendored files and CDN scripts need separate tracking.
Can I audit without a lockfile?
The docs describe a no-package-lock option, but results may differ between runs. Commit a lockfile for repeatable results.
Sources
- npm Docs, npm audit: https://docs.npmjs.com/cli/v10/commands/npm-audit
- npm Docs, package-lock.json: https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json
Last reviewed: 19 October 2026.