How to catch a supply-chain attack that npm audit misses
Advisory scanners such as npm audit, OSV-Scanner and Snyk compare your dependency versions with known, published vulnerabilities. They cannot see an attack committed into the repository itself, or one nobody has reported yet. Add an indicator-based check that reads the code: run npx am-i-hacked before the dev server and in CI, and pull with safe-pull so incoming commits are inspected before they reach your working tree. Run both kinds of check.
Two kinds of check
| Advisory scanners | Indicator scanner (am-i-hacked) | |
|---|---|---|
| Question asked | Is any dependency version on a list of known-bad versions? | Does the code in this tree look like an attack? |
| Finds | Reported CVEs and reported malicious package versions | Auto-run editor tasks, risky install scripts, obfuscated payloads, disguised executables, capture plus exfiltration, committed .env files |
| Misses | Anything not yet reported; anything committed into your repository | Known vulnerabilities in dependency versions; installed packages in node_modules |
Where to put the check
Before the dev server
{ "scripts": { "dev": "am-i-hacked && next dev" } }
A finding exits 1, so the dev server does not start until you have looked.
When pulling
safe-pull fetches, inspects the incoming commits before anything is written to disk, then fast-forwards. It flags a rewritten (force-pushed) upstream, an author and committer mismatch, editor auto-run tasks, download-and-run editor commands, disguised payloads, committed .env files and a dotenv plus node-fetch or axios dependency pair.
safe-pull --dry-run # inspect only
safe-pull # inspect, then merge --ff-only
In CI
GitHub Actions on ubuntu-latest has bash, jq and npx, but not ripgrep:
- run: sudo apt-get install -y ripgrep
- run: npx am-i-hacked@2
Pin the major version so a new release cannot change what your gate does without you noticing.
Install scripts
am-i-hacked flags package.json scripts that use curl, wget, powershell, child_process, node -e, base64 or eval. For dependencies, also stop install scripts you have not reviewed from running: npm ci --ignore-scripts, or pnpm, which from version 10 does not run dependency lifecycle scripts unless you allow them.
Other signals it checks
- Official Yarn release files committed to the repository, verified by SHA256.
.envfiles in the git index.- Python virtualenvs whose files no longer match their package
RECORDhashes, files no package owns, and.pthhooks that run code. This check ships in the next am-i-hacked release, after 2.0.1.
Limits
am-i-hacked does not scan node_modules and does not look up advisories, so keep your advisory scanner. It looks for warning signs; a clean result is not proof of safety.