npm Supply Chain Attacks Hit 1,300 Packages in ChainDrop Worm Campaign
The Shai-Hulud worm's sixth campaign hid malware in AI agent configuration files that scanners never read, while npm v12 and a Dependabot cooldown raced to close the gap.
vercel.com
In this article
On August 4, 2026, the npm package registry recorded the largest worm infection in its history: a self-propagating credential-stealing worm called ChainDrop had compromised more than 1,300 packages with a combined 2 billion monthly downloads, according to Bleeping Computer. Researchers tied ChainDrop to Shai-Hulud, the npm and PyPI worm that has mounted six major campaigns since September 2025 and has, with each wave, outrun the defensive measures the registry added in between. The August operation was not the first, and it was not the cleverest. It was the largest.
The infected package list included Keyv, a key-value storage library, Cacheable, and flat-cache, packages that sit deep in the dependency tree and rarely attract attention on their own. VentureBeat reported that an attacker had taken over the GitHub account of the developer who maintains Keyv, and that npm serves the library roughly 127 million times a week. Poisoned versions were live within hours. The incident did not rely on a new parser bug or a registry zero-day. It relied on possession of a legitimate maintainer account, which is the older and less glamorous problem.
"Worm" is not a metaphor here. ChainDrop spreads by publishing poisoned versions of packages from compromised accounts, steals credentials from the resulting installs, and repeats the cycle. CSO Online reported that security teams were being urged to perform full audits of developer machines, because an infected environment can publish again from every token it finds. That is the systemic failure underneath the Keyv incident: an account takeover does not stay an account takeover when the registry continues to trust the account.
Shai-Hulud's timeline explains how quickly a technique becomes commodity. The worm first surfaced in September 2025. Kaspersky Threat Research analyzed the patient zero package and mapped the self-replication path. By November, InfoWorld reported a faster version that executed malicious code during the preinstall phase. By May, Dark Reading reported that the operator calling itself TeamPCP had published Shai-Hulud source code to GitHub, and clones appeared within days.
That public source release changed the economics of every later campaign. ChainDrop did not need a team that could re-derive the worm from scratch. It needed maintainer credentials, a distribution strategy, and patience. VentureBeat's headline for the August incident made the point in a sentence: the poisoned packages did not fake their security check, they earned a legitimate one. Provenance cannot catch an intruder when the intruder is the provenance, and that is the failure mode the registry still lacks a clean answer for.
The AI agent blind spot
The genuinely new element of the August 4 campaign was not propagation. It was payload placement. MSN reported that Shai-Hulud introduced three capabilities it had never shipped before, including executable payloads planted inside AI coding agent files and IDE configuration directories. These files are settings, workspace context, and agent instructions that sit alongside source code but outside the code paths package scanners inspect. The choice was deliberate. A scanner that only reads package.json and installed JavaScript will not find a payload that lives in a Claude Code or VS Code configuration file.
The timing was not subtle. The day before ChainDrop hit, the AI track at BSides Las Vegas 2026 had spent two and a half days arguing that AI coding tools are the next major attack surface, MSN reported. The central claim was that the property that makes coding agents useful, their ability to read and write files across a project, is what makes them a persistence channel. ChainDrop then demonstrated the technique within 24 hours. It may be coincidence. It reads as an operator moving on the same observation researchers had just made in public.
The two named persistence formats in that campaign, Claude Code and VS Code configuration files, are not exotic. They are plain-text or near-plain-text files that load automatically when a developer opens a project. A payload planted there survives package replacement, because the install may complete cleanly and then the agent, not the installer, executes the follow-on action. This is a different attack surface from postinstall scripts, and it sits outside most registry-level controls, which are built around code execution at install time rather than file execution at project-open time.
Registry-level countermeasures
Two defensive changes landed this summer, and both are about time. On July 8, Tech Times reported that npm v12 would reach final release before the end of July, described as the package manager's most significant security redesign in its 16-year history. The release blocks install scripts, Git dependencies, and remote sources by default. The target was the mechanism that earlier campaigns, including North Korean attacks against Axios and Mastra AI, had used: postinstall hooks that execute code the instant a developer installs a package.
Separately, on July 26, Bleeping Computer reported that GitHub and PyPI added a time-based mechanism to Dependabot, the dependency management tool that now ships with a default three-day cooldown. The logic is straightforward and a little uncomfortable for engineering teams that have spent a decade automating dependency updates toward zero latency. The cooldown assumes that pulling the newest release immediately is a liability, because the newest release is the one most likely to have been published by an intruder during the first hours of a campaign.
The two defenses operate at different moments in the attack chain. npm v12 tries to stop malicious code from executing at install time. The Dependabot cooldown tries to stop a compromised release from being absorbed into thousands of projects before anyone notices. Neither addresses the August campaign's actual innovation, because neither control reads AI agent configuration files. A package can be published with clean installation scripts and still carry a payload in a Claude Code workspace file that the registry never inspects.
Python's registry has the same field of view. On March 24, 2026, PyPI hosted malicious versions of the LiteLLM library, specifically 1.82.7 and 1.82.8, Yahoo reported in a piece on the package registry layer. LiteLLM is infrastructure for AI applications. The attackers picked a library that would be pulled by systems built around models, not just by individual developers. Across npm and PyPI, the pattern is consistent: the target is not the dependency itself. The target is the agent infrastructure and CI/CD machines that consume the dependency automatically.
Container base images are the third surface in the same problem. A compromise in a base image propagates to every downstream image built on it, and unlike a registry package, the base image is often updated without a lockfile change visible to the application team. The npm and PyPI campaigns attract attention because their package names are concrete. The base-image version of the same failure is quieter and mostly shows up later in incident response, when the compromised layer has already been pulled into production. The registry layer and the image layer are now the same risk in different packaging.
What is known and what is not known should be stated separately. It is known that more than 1,300 packages were compromised. It is known that at least one maintainer account, the Keyv developer's GitHub, was taken over. It is known that the worm's source code has been public since May. It is not known how many developer machines executed the agent-file payloads, how many credentials were taken, or whether the campaign's exfiltration is already complete. The verbs could and did do different work, and most of the residual risk lives in the gap between them.
For incident responders, the August episode resolves a year-long question about whether registry malware would move from install-time execution into persistence inside agent tooling. It has moved. The residual risk is that most scanner roadmaps still treat package contents as code, not as configuration, and agent workspace files fall outside every default rule. A worm that depends on an unread file format will be undercounted until scanning catches up with the file format itself. The countermeasure that has not yet shipped is scanner awareness of AI agent file formats.
The reason that countermeasure is missing is not technical. The files are local, small, and produced by tools that change their formats often. A scanner that parses every Claude Code or VS Code settings variant would be brittle, and security vendors have been slow to invest in brittle detections. ChainDrop exploited that gap, and the gap remains open for the next variant that changes a filename. What looked like an exotic trick in August is better understood as the predictable next file category after install scripts, and the security industry is currently behind by one file category.
There is a temptation to call this evolution sophisticated. It is not. It is patient, and it is specific about where security tools do not look. The same can be said of the May 19 campaign in which a compromised maintainer account pushed 639 malicious versions across 323 packages in under 30 minutes, as reported by MSN. Speed and coverage are not sophistication; they are automation. Defenders keep describing these campaigns as advanced, and that description keeps obscuring the fact that the attack surface is a list of default locations.
The provenance problem remains unsolved. VentureBeat reported in May that any environment that had installed or imported one of the 172 compromised npm or PyPI packages published since May 11 should be treated as potentially compromised. The recommendation was blunt because the detection surface is uncertain. Valid provenance from a compromised maintainer account is still the hardest problem in package security, and the August incident is the strongest recent proof that the problem has not gone away.
What to watch next is not a product announcement. It is a measurement. If npm v12 blocks install scripts by default and Dependabot's three-day cooldown slows propagation, the next Shai-Hulud variant should reach a smaller population, even if the agent-file payload technique escapes scanning. A sharp drop in infected package counts would not mean the technique is gone. It would mean the registry-level controls are doing their job, and the remaining infection is hiding precisely where scanners choose not to look.
The forward checkpoint is the next 90 days. ChainDrop arrived roughly 12 weeks after the source code release and three weeks after npm v12 shipped. Registry maintainers and incident responders will be watching whether the sixth campaign is the last one built on account takeover plus install scripts, or the first one built on account takeover plus agent persistence. The answer will show up in the next worm's distribution numbers, before anyone has to debate the classification.