npm supply chain attacks: how they work and how to detect them

An npm supply chain attack does not breach your perimeter. It poisons a dependency you already trust, and waits for your build system to pull it in.
Developers install billions of packages every day and rarely audit the code inside them. When an attacker controls a popular package, a single malicious release fans out to every project that installs or updates it, often within minutes. Sonatype counted more than 454,600 new malicious open-source packages in 2025 alone, a 75% increase year over year. The attacks that defined 2026 were not opportunistic. They were coordinated, state-linked, and in several cases self-replicating.
This post covers how the three main attack vectors work, what distinguishes them, and what detection actually requires.
The three vectors#
1. Account takeover#
The attacker compromises a legitimate maintainer's credentials and publishes a malicious version of a package the maintainer already owns. The package retains its real name, its real history, and its real download count. Nothing in the registry signals that anything changed.
This is how the debug and chalk compromise happened in September 2025. An attacker phished the GitHub account of Qix, a maintainer with publish rights to both packages. debug has 300 million weekly downloads. chalk has 400 million. Within two hours, malicious versions were running in an estimated 10% of cloud environments. Amazon's 2026 attribution report later connected this to North Korea's Sapphire Sleet. The packages had no CVEs. A vulnerability scanner would have passed them clean.
The axios compromise on March 31, 2026 followed the same pattern. A fake support domain was used to phish the lead maintainer's npm account credentials. Between 00:21 and 03:20 UTC, two trojanized versions were published to a package present in approximately 80% of cloud environments. The malicious versions added a fabricated dependency whose only purpose was to deploy a cross-platform remote access trojan. No CVE. No registry warning. 100 million weekly downloads.
Account takeover is the hardest vector to defend against at the registry level because the attacker is acting as a legitimate account. Two-factor authentication and token scoping reduce the risk but do not eliminate it. The 2026 campaigns found paths around both.
2. Dependency confusion#
The attacker publishes a public package with the same name as an internal or private package used by a specific organization. Package managers, by default, resolve names against the public registry first. When the public malicious version has a higher version number than the internal one, some configurations will install the attacker's package instead.
Research from Orca Security found that as many as 49% of organizations have at least one asset vulnerable to dependency confusion. In 2026, attackers have become systematic about finding internal package names before registering them. The sources include job postings that mention specific internal tools, GitHub repositories with inadvertently committed configuration files, error messages in public issues, and Docker layer metadata that exposes package installation commands.
The syft-acp cluster Attestd documented in July 2026 is a dependency confusion attack targeting Anchore's internal SBOM tooling namespace. The sme-rko-finance cluster detected in August targets Tinkoff Bank's internal frontend monorepo. In both cases the attack is highly targeted, using internal naming conventions derived from reconnaissance of the organization's public presence.
3. Typosquatting and slopsquatting#
Typosquatting registers names visually similar to popular packages: 1odash for lodash, requesfs for requests. The attacker waits for a developer to mistype an install command.
Slopsquatting is the 2026 evolution. Rather than exploiting human typing errors, it exploits the package names that AI coding assistants consistently hallucinate. Commercial models hallucinate packages at a 5.2% average rate. 43% of hallucinated names repeat on every run of the same prompt, making them predictable and registrable in advance. Amazon's July 2026 attribution report explicitly identified slopsquatting as an active tactic in the Sapphire Sleet campaign. A 700-package Russian campaign using AI-hallucinated names landed in August. Neither of these attacks requires any interaction with the victim. The hallucination does the distribution.
The slopsquatting explainer covers the mechanics and the 2026 cases in detail.
What 2026 added: self-replicating worms#
Earlier supply chain attacks required the attacker to push a malicious version manually. The Shai-Hulud worm family changed this. The worm steals npm tokens from infected development environments and uses them to publish malicious versions of other packages the token has rights to. One compromised maintainer becomes the vector for hundreds of additional compromises.
ChainDrop in August 2026 demonstrated the scale this enables. A single compromised GitHub account propagated across 400+ packages with a combined 2 billion monthly downloads within hours. The malicious versions were published through the legitimate GitHub Actions workflow with valid provenance attestations. Checking provenance returned a clean signal.
Why CVE scanners miss these attacks#
Every account takeover and slopsquatting attack listed above has one thing in common: no CVE.
CVE databases record vulnerabilities in legitimate package code. They do not record malicious versions of legitimate packages. A CVE scanner checks whether a package version has a known vulnerability. It does not check whether a package version was published by someone who compromised the maintainer's account.
[email protected] has no CVE. [email protected] has no CVE. keyv at the ChainDrop-compromised version has no CVE. The Shai-Hulud worm packages have no CVEs. A scanner that checks vulnerability records passes all of them clean.
The supply chain compromise signal is independent of the CVE signal. A package can have a known CVE and a clean supply chain. A package can have a compromised supply chain and zero CVEs. Both signals matter and they come from different sources. The case for checking both is at attestd.io/vs-nvd.
What detection actually requires#
Detecting supply chain attacks requires a signal that is independent of CVE databases and that fires on the specific versions that were compromised, not just on the package name in general.
Three things matter:
Version-specific compromise data. The malicious payload exists in specific versions, not the entire package. [email protected] is compromised. [email protected] is clean. A detection system that returns a package-level signal rather than a version-level signal is not useful for remediation.
A continuously updated feed. The window between a malicious publish and registry removal is measured in hours. A detection system that updates weekly or monthly will not catch the attack before most installations happen.
Independence from the package registry. The registry removed the malicious versions. A scanner that checks the registry after removal will find nothing to flag. The intelligence needs to persist in a separate system that records what was compromised and when.
Attestd's supply chain monitoring layer returns version-specific compromise status sourced from OSV MAL advisories and the autonomous detection pipeline, independent of whether the package is still on the registry. For the Sapphire Sleet campaigns and for ChainDrop, this means the compromised versions return risk_state: critical with supply_chain.compromised: true regardless of registry state.
For teams integrating supply chain checks into CI/CD pipelines, the use-cases/cicd page covers the integration patterns. For AI agent pipelines specifically, the use-cases/ai-agents page covers why autonomous systems have a different exposure profile from human-reviewed workflows.
The practical checklist#
Disable install scripts by default. npm install --ignore-scripts prevents lifecycle hooks from running automatically. This stops preinstall and postinstall vectors but does not stop import-time execution, which the JoyFill, ViteVenom, and Alibaba campaigns all used in 2026.
Pin lockfiles and use them in CI. npm ci enforces the exact versions in package-lock.json. It does not protect against a compromised version that was pinned before the compromise was discovered.
Check supply chain status before installing. A pre-install API call that returns supply_chain.compromised: true on a package in the lockfile stops the install before anything executes. This is the check that catches what all the other controls miss.
Monitor for new compromises on packages already installed. A lockfile that was clean last week may contain a newly compromised version today. Continuous monitoring against installed versions, not just pre-install checks, catches this.
Rotate credentials from affected environments. If a compromised package ran in an environment, treat every credential accessible from that process as potentially exfiltrated. The 2026 campaigns targeted npm tokens, GitHub tokens, cloud credentials, and AI provider API keys. Patching or upgrading the package does not revoke credentials already harvested.
Coverage#
Attestd's supply chain monitoring covers major 2026 campaigns including Sapphire Sleet (debug, chalk, axios), ChainDrop (keyv, flat-cache), Shai-Hulud and its variants, ViteVenom, JoyFill, mrmustard, the Alibaba dependency confusion cluster, and hundreds of smaller campaigns. All return version-specific risk_state and supply_chain.compromised signals. Detection ledger: github.com/attestd-io/detection-ledger.
Related
EditorialSupply chain compromise vs CVE: why `risk_state: none` does not mean safe
A package can have no CVE and still be malicious. Learn why CVE risk and supply chain compromise require independent security signals.
Robert8 min read
EditorialHow to audit your npm dependencies in 30 minutes
A practical 30-minute npm dependency audit covering CVE scanning, lockfile inspection, supply chain compromise checking, typosquat detection, and CI
Robert7 min read
EditorialWhy CVSS scores mislead autonomous systems
CVSS measures theoretical severity. Only 2.3% of CVSS 7+ vulnerabilities get exploited. 28% of exploited CVEs score medium. Here is what systems need instead.
Robert8 min read