I first wrote about NPM typosquatting back in 2022 as an early warning that a tiny typo in a package name could open the door to serious compromises. Fast-forward to today: the debug/chalk compromises and the Shai-Hulud worm have proven just how right that warning was. This post updates the original guidance with fresh lessons and a practical checklist.
NPM is fantastic. Modern development owes a huge debt to the open-source ecosystem and the thousands of contributors who share their work. That scale and velocity, however, come with tradeoffs, and one of those tradeoffs is supply-chain risk.
You may remember typosquatting as the simple social-engineering trick where an attacker publishes a package whose name is one character off from a popular library (e.g., crypto-js → cyrpto-js). That attack vector is still real and dangerous, but in September 2025, the community got a reminder that threats have grown a lot more sophisticated. Two recent incidents show how quickly things can escalate:
- A wave of popular packages (including debug, chalk, and many dependencies) was trojanized after a maintainer token/phishing compromise, with malicious versions published to npm. Security teams and vendors documented malicious versions that attempted browser-side theft of crypto funds and similar actions. Aikido+1
- Worse: an active, self-replicating worm campaign (“Shai-Hulud”) has been observed that injects obfuscated malware into packages, harvests secrets (npm tokens, GitHub credentials, cloud keys), and spreads laterally across the npm ecosystem, compromising hundreds of packages and creating persistent CI/CD backdoors. This is now being tracked and analysed by Unit 42 and other firms. Unit 42+1
If you thought typosquatting was a quaint risk limited to the occasional prank package, these attacks show why supply-chain hygiene has moved from “nice to have” to “mission critical.”
What makes this different now
- Scale & reach. When highly popular transitive dependencies are compromised, billions of installs can mean a few malicious lines of code reach lots of builds and CI pipelines very quickly. JFrog
- Automated propagation. Worm-style payloads can extract credentials and publish malicious versions themselves, turning a single compromise into an epidemic. Unit 42
- CI persistence. Attackers can add hidden workflows or backdoors in repositories that exfiltrate secrets during CI runs, not just on end-user machines. wiz.io
Quick risk model (what an attacker can do)
If a typosquat or trojanized package gets into your dependency tree (or a wormed package is a transitive dep), the attacker might:
- Add sub-dependencies that bloat or slow apps (supply-side DoS).
- Execute code during install or at runtime (data exfiltration, remote command execution).
- Try to run silent crypto-miners or replace crypto addresses in browser contexts.
- Harvest credentials (npm tokens, GitHub secrets) and pivot to other packages or repositories. Cycode+1
Terrifying? Yes. Treat it like a systemic failure mode: the attack surface is not just your repo, it’s your developer machines, your CI, and your artifact caches.
How to spot suspicious packages (practical checks)
When you add new packages, or audit existing ones, watch for these signals (your original checklist, tightened):
- Name oddities: small spelling changes, extra/removed hyphens, capitalization changes. (e.g., crypto-js vs cyrpto-js)
- New/odd publish cadence or an unusually fresh package with a high version number.
- Very few dependents, no repo link, or repo→npm contributor mismatch.
- Obfuscated postinstall / install scripts, unexpected node/gyp hooks, or binary artifacts.
- Short or spiky download history that doesn’t match the package’s claimed purpose.
- Unexpected transitive dependencies or newly introduced dependencies in a minor bump.
If something flags, open the package page, inspect the repository (commits, authors), and check the package.json / README/release tags before trusting it.
Concrete defensive checklist (what to do right now!)
Audit & inventory
- Generate a dependency inventory from package-lock.json / yarn.lock and scan for known-bad versions. (Use npm ls + lockfiles to find transitive exposure.)
- Run SCA/SAST tools (Snyk, OSS-scanners, whitelisting tools) across your repos. Cycode
Lock & pin
- Pin production dependencies to fixed versions (avoid unbounded ranges like ^ in production). Use package-lock.json or npm ci for reproducible installs. CISA guidance now explicitly suggests pinning to known safe releases. CISA
Harden CI / Artifacts
- Do not store long-lived secrets in repos. Rotate and revoke tokens now if you suspect exposure.
- Audit GitHub Actions and other workflows: remove any unexpected workflows, and restrict who can create/modify workflows. Unit 42
- Use internal artifact caches/proxy registries (Verdaccio, Nexus, Artifactory) to control what gets fetched into builds.
Install-time protections
- Avoid running install scripts you don’t understand. For ad-hoc installs, npm install --ignore-scripts blocks postinstall hooks. (Useful for quick checks; less practical for full builds but great for triage.)
- Scan packages for suspicious obfuscated bundles or minified payloads that appear unrelated to the library’s function.
Developer hygiene
- Rotate developer npm and GitHub tokens, enable MFA, and enforce least privilege on tokens. CISA
- Educate the team: show examples of typosquats and compromised package.jsons so the “gut-check” becomes routine.
Monitoring & response
- Add alerts for unexpected changes in lockfiles or direct dependency bumps in PRs.
- Keep a short incident runbook: isolate builds, rotate tokens, revert to pinned safe versions, and notify downstream consumers.
If you find suspicious packages, report them!
- Report on npm (there’s a “Report malware” flow on each package page).
- Report to Snyk or other security vendors (many accept disclosure reports). Cycode
- Share the IOCs and disclosure with your community and internal teams so others aren’t tripped up.
Short checklist for maintainers (if you own packages)
- Enable 2FA for npm and GitHub accounts.
- Avoid storing tokens in places that can be harvested by search tools or history.
- Lock down CI credentials and restrict who can publish.
- Add automated scans on PRs to detect suspicious code patterns or obfuscation.
Why this matters to you (TL;DR)
Typosquatting is no longer just the lonely cyrpto-js prank — the recent debug/chalk compromises and the Shai-Hulud worm show that compromise can scale, self-propagate, and target CI pipelines and secrets. The safer the ecosystem, the more resilient your org will be.
For a repeatable, auditable approach to this problem, including CI controls, runbooks, checklists, and supply-chain-specific modules, check out our Cybersecurity Launchpad security program streams. They're built to help teams get a defensible posture quickly (CI hardening, SCA integrations, evidence maps, and runbooks).
Further reading and incident write-ups
- Aikido’s investigation of the debug / chalk compromises. Aikido
- Unit 42’s analysis of the “Shai-Hulud” worm that affects npm packages. Unit 42
- CISA guidance on reviewing dependencies and pinning versions. CISA
When I called out typosquatting in 2022, it was easy to dismiss as a niche risk. Today’s supply-chain compromises show it’s systemic. If you want more than one-off fixes, check out our Cybersecurity Launchpad security program streams, built to be a practical kit with dependency inventory templates, CI/CD hardening steps, GitHub Action snippets, and a one-page incident runbook. Start building a defensible posture before the next compromise makes headlines.
Shane Fast