npm
The JavaScript package registry behind Node.js apps and many web front ends.
About
npm is the public registry for JavaScript packages, and the tool that installs them. A Node.js app names the packages it needs, and those often pull in hundreds more of their own. Each one is code from outside the team, fetched whenever the app is built.
A package can carry install scripts, commands that run the moment it is installed, with the rights of whoever installs it, on a laptop or a build server. The rest of its code runs inside the app at every start, or in visitors' browsers when it is bundled into the front end.
If It Is Malicious
If an npm package is malicious, it runs inside a Node.js app with the app's rights, on every developer laptop and build server that installs it.
See It in the StackExamples
These are well-known names from npm, written as you would meet them in an inventory, an alert or a lockfile, the file that records every version a build installed.
express- The web framework many Node.js apps are built on.
react- The library many web front ends are built with.
lodash- Utility functions found in a great many Node.js apps.
chalk- Colours text in the terminal. It was hijacked in September 2025.
debug- A small logging helper that thousands of packages depend on.
How Bad Code Gets In
These are the ways bad code can reach your systems through npm. None of them needs a flaw in your own code, so outside code needs checking as much as your own.
- A maintainer's account or publishing token is stolen, and a bad version goes out under the real name.
- A new maintainer, given control of a popular package, adds hidden code, sometimes through a new dependency.
- A maintainer sabotages their own package on purpose, to make a point.
- A package named like a popular one catches mistyped installs.
- A public package with the same name as an internal one is installed in its place.
- A worm uses the tokens it steals to publish infected versions of more packages.
How to Check
These checks show what came from npm, whether a known bad version is in use, and how to keep one out next time.
- Commit
package-lock.jsonand install withnpm ci, so every build gets exactly the reviewed versions. - Run
npm audit, or match the lockfile against OSV and GitHub advisories, in every build. - When an incident breaks, search every lockfile and image for the named versions.
- Install through a private registry or proxy that can hold back brand-new versions.
- Turn off install scripts where a build does not need them, with npm's
ignore-scriptssetting. - Check registry signatures and provenance with
npm audit signatures.
Well-Known Incidents
Each incident below is a real case, told at the level of its public advisory. The tag says how the bad code got in, and the link opens the primary source.
Malicious Update2018
event-streamTakeoverA stranger offered to maintain a popular stream library, was given control of it, and added a new dependency carrying hidden code aimed at one bitcoin wallet app.
Reach The library was widely used, but the code only woke inside the release build of the Copay wallet app. Copay shipped it to users, set to steal the keys of wallets holding large balances.
Affected
Source: blog.npmjs.org (opens in a new tab)event-streamflatmap-streamDependency Confusion2021
Dependency Confusion Research
A researcher showed that the build tools of many large companies would fetch a public package in place of an internal one with the same name.
Reach His test packages, which only reported back, ran inside more than 35 organisations through npm, PyPI and RubyGems. Apple, Microsoft and PayPal were among them.
Source: medium.com (opens in a new tab)Hijacked Account2021
ua-parser-jsHijackAttackers took over the maintainer's npm account and published three versions that installed a cryptominer and, on Windows, a password stealer.
Reach Many other libraries depend on it, so laptops and build servers that installed a bad version ran the malware. Every password, key and token on them had to be changed.
Affected
Source: cert.europa.eu (opens in a new tab)ua-parser-jsProtestware2022
Two Libraries Sabotaged by Their Author
Saying he would no longer work for free, the author of two popular libraries released versions that broke them on purpose. One printed endless garbage, and the other was emptied.
Reach Apps and tools that took new versions automatically broke at once, Amazon's AWS Cloud Development Kit among them.
Affected
Source: snyk.io (opens in a new tab)colorsfakerProtestwareCVE-2022-238122022
node-ipcProtestwareIts maintainer added code that overwrote files on machines whose IP address placed them in Russia or Belarus, then a module that left a protest message on the desktop.
Reach Developers got it through tools that depended on it. Vue CLI pulled in the version with the desktop message, though its users never chose node-ipc.
Affected
Source: snyk.io (opens in a new tab)node-ipcpeacenotwarHijacked Account2025
The
chalkanddebugTakeoverAttackers took over a maintainer's account with a phishing email from a fake npm support address, and bad versions of chalk, debug and other basic packages went out.
Reach Together they are downloaded billions of times a week. The code targeted cryptocurrency payments in web pages that bundled it, and most bad versions were removed the same day.
Affected
Source: aikido.dev (opens in a new tab)chalkdebugansi-stylesstrip-ansisupports-colorwrap-ansiHijacked Account2025
Shai-Hulud Worm
A worm spread through npm by itself. Each infected package took the installer's tokens and secrets, posted them to public GitHub repositories, and used them to infect more packages.
Reach Hundreds of packages were infected, some published by a security vendor, and a larger second wave followed in November 2025.
Affected
Source: cisa.gov (opens in a new tab)@ctrl/tinycolor
In Common Stacks
These common stacks take code from npm. Open one to see where that code sits among its layers and who runs each one.