How to audit your npm dependencies in 30 minutes

Most dependency audits happen reactively: a security alert fires, a CVE makes the news, someone on the team forwards a BleepingComputer article. The audit that happens in response to an incident is better than no audit at all, but it misses the attacks that are not generating headlines yet.
This is a practical 30-minute process you can run today and repeat quarterly. It covers what npm audit and your existing scanner check, what they miss, and how to close the gaps without buying an enterprise security platform.
Minutes 0-5: run what you have#
Start with the tools already in your project.
npm audit
This checks your installed packages against the GitHub Advisory Database. It catches CVEs, some GHSA advisories, and version ranges that have known vulnerabilities. Run it, read the output, note anything at high or critical severity.
If you have Snyk installed:
snyk test
Snyk adds some advisories that npm audit misses and provides more context on exploitability. The output overlaps significantly with npm audit but catching the delta is worth the extra minute.
What these tools do not check: supply chain compromises, typosquatted package names, AI-hallucinated package names that an attacker has registered. More on those in the next sections.
Minutes 5-15: check your lockfile for red flags#
Your package-lock.json or yarn.lock is the authoritative list of everything that will be installed. Most developers never read it in full. You should spot-check it.
Check for packages you did not knowingly install. Run:
cat package-lock.json | grep '"resolved"' | awk -F'"' '{print $4}' | sort | uniq
This gives you every resolved package URL. Scan for anything that looks unfamiliar or that resolves to an unexpected registry. A legitimate project should resolve everything to registry.npmjs.org. Anything resolving elsewhere is worth investigating.
Check for very recent package additions. If a dependency appeared in your lockfile in the last week and you did not explicitly add it, find out why. Most of the 2026 supply chain attacks published malicious versions and relied on automatic update policies or dependency trees pulling in the new version.
Check for unusual version strings. Versions like 99.0.0 or 999.9.9 are a common dependency confusion indicator. An attacker publishing a public package to shadow a private internal one often uses an artificially high version number to win the resolution race. If you see version numbers that do not follow a package's normal release history, investigate.
Check for packages with no legitimate publisher history. For any package you did not explicitly install, check its npm page. A package with one version, no README, and a publish date from last week is a red flag even if it has no known CVE.
Minutes 15-20: check for supply chain compromises on your key dependencies#
CVE scanners check vulnerability records. Supply chain compromises do not generate CVEs. A package where an attacker published a malicious version using a stolen maintainer credential has no CVE, no npm audit flag, and no Snyk finding.
The fastest way to check your dependencies against known supply chain compromises is to query a supply chain monitoring API for your key packages. You do not need to check every package. Start with the highest-risk ones: packages with direct network access, packages that run at build time with access to your environment variables, and packages with very high download counts.
A sample check for a key dependency. This shows what a confirmed supply chain compromise looks like versus a clean version:
curl "https://api.attestd.io/v1/check?product=debug&version=4.4.2" \
-H "Authorization: Bearer $ATTESTD_API_KEY"
{
"product": "debug",
"version": "4.4.2",
"supported": true,
"risk_state": "critical",
"risk_factors": ["supply_chain_compromised"],
"actively_exploited": false,
"patch_available": false,
"fixed_version": null,
"confidence": 0.95,
"cve_ids": [],
"supply_chain": {
"compromised": true,
"sources": ["osv"],
"malware_type": "malware",
"description": "Malicious code in debug (npm)",
"compromised_at": "2025-09-08T14:26:51Z",
"removed_at": null
},
"supply_chain_monitored": true
}
A response with supply_chain.compromised: true and an empty cve_ids array is exactly the case CVE scanners miss. This version has no vulnerability record, no CVE, and no npm audit flag. Only the supply chain signal catches it.
For a bulk check across all your dependencies, the check-action GitHub Action can scan your lockfile automatically in CI.
Minutes 20-25: check for typosquatting and slopsquatted names#
This is the step most audits skip entirely because existing tools do not check for it.
AI-hallucinated package names are an emerging attack vector. Language models suggest package names that do not exist, at a rate of roughly 5.2% across tested prompts. Attackers register those predictable names before a developer or an autonomous agent installs them. If your project uses AI coding tools, this is a real exposure.
What to look for: any package in your dependencies that you do not recognise and that has a low install count, a recent first-publish date, and a name that sounds like it could be a utility library. The pattern is plausible-sounding names with no real user base.
The quick check: for any unfamiliar package name, run:
npm info package-name
Look at the publish date, the weekly downloads, and whether there is a meaningful README. A package with 47 weekly downloads, a publish date from last month, and a one-line README that just says "utility functions" deserves scrutiny regardless of whether it has a CVE.
For packages with typosquat or hallucination signals, the Attestd supply chain API returns a typosquat field with a kind that can be hallucination or typosquat and a list of likely_intended packages. This is the check that catches a package named react-codeshift before it executes.
Minutes 25-30: review your update policy and CI configuration#
The last five minutes are about preventing the next incident rather than finding the current one.
Are you running npm install or npm ci in CI? npm ci uses the lockfile exactly. npm install can resolve different versions depending on what is available at the time. If you are running npm install in CI, switch to npm ci.
Do you have automatic dependency updates enabled? Dependabot and Renovate are useful but they create a window where a newly published malicious version can enter your lockfile before any human reviews it. If automatic updates are enabled, add a supply chain check as a gate before the update is merged.
Are install scripts disabled by default? The 2026 attacks split between install-time execution (postinstall hooks) and import-time execution (malicious code in the module itself). Disabling install scripts with --ignore-scripts stops the first category. It does not stop the second. Know which category your current dependencies are in.
Do you have a process for reacting to a supply chain compromise? When a package in your lockfile is flagged as compromised, what happens? If the answer is "it depends on who notices the BleepingComputer article," that is the process gap to close. A webhook from a supply chain monitoring service that fires when a package you depend on is compromised gives you a structured notification path rather than relying on manual discovery.
What a 30-minute audit does not replace#
This process is a practical starting point. It is not a replacement for continuous monitoring. Packages that are clean today can be compromised next week. A quarterly audit catches a snapshot; continuous monitoring catches the event when it happens.
It is also not a substitute for the supply chain check in your CI pipeline. The audit you run today on your current lockfile does not protect you from a compromised version entering tomorrow's build.
The use-cases/cicd page covers how to integrate supply chain and CVE checks into a pipeline so that every build verifies its dependencies rather than relying on periodic manual audits.
For the broader context on what the current threat landscape actually looks like, the state of npm supply chain security in 2026 covers the major 2026 campaigns and the techniques that a 30-minute audit would and would not have caught.
Related
EditorialSupply chain compromise vs CVE: why `risk_state: none` does not mean safe
A package can have no CVE and still be malicious. Learn why CVE risk and supply chain compromise require independent security signals.
Robert8 min read
EditorialWhy CVSS scores mislead autonomous systems
CVSS measures theoretical severity. Only 2.3% of CVSS 7+ vulnerabilities get exploited. 28% of exploited CVEs score medium. Here is what systems need instead.
Robert8 min read
EditorialWhat every developer should know about dependency security
CVE scanners miss supply chain attacks. Lockfiles are not guarantees. AI tools introduce new vectors. Here is what dependency security requires in 2026.
Robert6 min read