Malicious npm packages are libraries published to the npm registry that intentionally run harmful code — stealing credentials, mining cryptocurrency, exfiltrating source code, or wiping files — rather than containing an accidental bug or unpatched CVE. They reach victims the same way any dependency does: a developer runs npm install, a CI pipeline resolves a lockfile, or a transitive dependency gets pulled in three levels deep without anyone reviewing it. Because npm has no pre-publish code review and over 3.1 million packages in its registry, it has become the most heavily targeted open-source ecosystem for supply chain attacks. In September 2025 alone, attackers compromised npm packages with a combined 2 billion weekly downloads in a single phishing incident. This post defines what makes a package malicious, how attackers get code onto npm, what the largest documented incidents looked like, and how defenders can detect and stop these packages before they reach production.
What Is a Malicious npm Package?
A malicious npm package is one where the intent of the code is to harm the user, host, or organization that installs it — as opposed to a vulnerable package, which has an unintentional security flaw like a buffer overflow or injection bug. The distinction matters operationally: a vulnerable package (say, one with a known CVE) gets fixed with a patch release, and scanners like npm audit or Snyk flag it against a CVE database. A malicious package has no CVE most of the time, because it was never a "flaw" — it's designed to look legitimate. Common payload types include credential and environment-variable theft (reading .npmrc, AWS keys, or .env files), cryptocurrency wallet drainers that intercept clipboard contents or hijack transaction signing, cryptominers that hijack CI/CD compute, reverse shells for persistent access, and "protestware" that deliberately damages systems based on IP geolocation. Detection requires behavioral and provenance analysis — not just version-matching against a vulnerability database — because the code itself, not a known flaw, is the threat.
How Do Attackers Get Malicious Code Into npm?
Attackers get malicious code into npm primarily through four vectors: typosquatting, dependency confusion, maintainer account takeover, and malicious version updates to already-trusted packages. Typosquatting relies on developer typos or copy-paste errors — packages like crossenv (targeting cross-env) or discord.js lookalikes such as discord.dll have been used to catch misspelled installs. Dependency confusion exploits internal package names that also exist publicly; if a company has an internal package called acme-utils and never published it to the public registry, an attacker who publishes a higher-versioned acme-utils to npm can get it pulled by misconfigured internal build tooling. Maintainer account takeover is the highest-leverage vector because it compromises packages with existing trust and massive download counts — this is what happened in the September 8, 2025 npm incident, where a phishing email impersonating npm support ("npmjs.help") compromised the account of a maintainer responsible for chalk, debug, ansi-styles, strip-ansi, color-convert, and roughly 15 other packages, which together see billions of weekly downloads. A related but distinct pattern is self-propagating worms: also in September 2025, a worm dubbed "Shai-Hulud" used compromised npm publish tokens to automatically inject itself into hundreds of downstream packages, run TruffleHog against local secrets, and exfiltrate stolen credentials to public GitHub repositories created under victims' own accounts.
What Have Been the Biggest Malicious npm Package Incidents?
The biggest malicious npm package incidents include the 2018 event-stream attack, the 2021 ua-parser-js compromise, the 2022 node-ipc protestware, and the 2025 chalk/debug and Shai-Hulud campaigns. In November 2018, a maintainer handed off event-stream (roughly 2 million weekly downloads at the time) to an unknown contributor who added a dependency, flatmap-stream, containing code that specifically targeted the Copay Bitcoin wallet application to steal private keys and passwords. In October 2021, ua-parser-js — used by an estimated 7 million-plus projects — was compromised for about an hour across versions 0.7.29, 0.8.0, and 1.0.0, during which installers received a password-stealing trojan and a cryptocurrency miner on both Linux and Windows hosts. In March 2022, the maintainer of node-ipc (used by the popular vue-cli) shipped versions that detected Russian and Belarusian IP addresses and overwrote files with a heart emoji as a form of protest over the invasion of Ukraine — a reminder that "malicious" doesn't require an external attacker, since a trusted maintainer can weaponize their own package. The September 2025 incidents were the largest by download-count exposure to date: the phished-maintainer compromise touched packages with a combined ~2 billion weekly downloads, injecting a crypto-clipper that silently swapped wallet addresses in browser transactions, while Shai-Hulud independently compromised over 180 packages (including some published by security vendors) through automated propagation rather than manual attacker effort.
How Many Malicious Packages Are Published to npm Each Year?
Tens of thousands of malicious packages are published to npm annually, and the volume has grown sharply year over year. Sonatype's supply chain research has tracked a roughly 1,300% increase in malicious open-source packages across npm, PyPI, and other registries between 2020 and 2023, driven mostly by automated typosquat generation. Socket's 2024 threat research reported detecting several thousand malicious npm packages per month, with spikes tied to automated campaigns that publish dozens of near-identical typosquats of popular packages (like react, lodash, or axios) within minutes of each other. Because npm has no mandatory pre-publish review, publishing cost is close to zero — an attacker can script the creation of hundreds of throwaway accounts and packages per day, so raw package count is a weak signal; what matters for defenders is download velocity, install-time script behavior (preinstall/postinstall hooks), and whether a package appears as a transitive dependency inside code paths that actually execute in production.
How Can Security Teams Detect Malicious npm Packages Before They Reach Production?
Security teams detect malicious npm packages before production by combining behavioral analysis of install-time scripts, provenance/maintainer-change monitoring, and reachability analysis rather than relying solely on CVE feeds. Because most malicious packages have no CVE, traditional SCA tools that only match dependency versions against vulnerability databases will miss them entirely — the package that shipped the event-stream attack, for example, would have shown zero known CVEs the day it was installed. Effective detection instead looks at signals like: newly-added or sudden postinstall scripts that make outbound network calls, maintainer or ownership changes on high-download packages within a short window, code that reads environment variables or .npmrc/.aws/credentials files without a clear functional reason, and whether the flagged package is even reachable from code your application actually calls at runtime. That last point is critical for prioritization: an organization with 4,000 dependencies might have 30 flagged as suspicious, but if only 3 are reachable in an executed code path, that's where incident response should start first — not the other 27 sitting dormant in an unused dev-tool.
How Safeguard Helps
Safeguard helps security teams cut through this noise with reachability analysis that determines whether a flagged npm package's malicious or vulnerable code path is actually invoked by your application, so triage starts with the handful of packages that pose real risk instead of hundreds that don't. Griffin, Safeguard's AI analysis engine, reviews package behavior, maintainer and publish-history changes, and install-script activity to flag suspicious npm packages — including newly published typosquats and compromised maintainer accounts — before they're merged into a dependency tree. Safeguard generates and ingests SBOMs across your repositories so you have a continuously current inventory of exactly which package versions are running where, which is what let organizations using SBOM tooling identify their exposure to the September 2025 chalk/debug compromise in minutes rather than days. When a malicious or high-risk package is confirmed, Safeguard opens an auto-fix pull request that pins or replaces the affected dependency, so remediation ships as fast as the detection did.