Supply-chain case study
ChainDrop · began 4 Aug 2026 · updated 5 Oct
On 4 August 2026 a self-replicating worm tore through the npm
keyv and cacheable ecosystem — hundreds
of poisoned package versions, a preinstall script that
harvests every credential it can reach, and a nastier twist than
its predecessors: it plants persistence hooks in
Claude Code and VS Code.
Microsoft has since dissected the campaign under the name
ChainDrop. Here is what
it does, and — honestly — where a registry helps and where it
doesn't.
keyv/cacheable/cache-manager
version since 4 Aug 2026 as credential-exposed. Pin exact versions
from a known-good lockfile, and rotate GitHub, npm, cloud and SSH
credentials — but remove the malware's credential-revocation
watcher first (see mitigations below), or it fights your rotation.
What happened
Starting with keyv@6.0.0, malicious releases
carried a preinstall script that executes a
~727 KB compiled bundle — pulling down Bun 1.3.13 from
GitHub if it isn't already present. The payload harvests GitHub,
npm, cloud, HashiCorp Vault, Kubernetes, database and
private-key material, and even reads GitHub Actions runner
memory. It carries its own npm-publishing machinery, which is
what makes it a worm: stolen npm tokens are immediately used to
poison the next set of packages, autonomously.
The new twist is persistence through developer tooling. The
malware writes a SessionStart hook into
.claude/settings.json and an "Environment Setup"
task with runOn: folderOpen into
.vscode/tasks.json — so simply opening the
repository later re-executes the payload. (VS Code blocks
automatic tasks in untrusted workspaces and Claude Code applies
workspace-trust protections, which blunts but does not erase
this vector.) Exfiltration flows out through GitHub repositories
created under the compromised identities.
Scale depends on who's counting, because tags are changing faster than trackers can freeze lists: SafeDep verified 353 poisoned versions across 79 names; Aikido's monitoring put it at 868+ packages across 1,381+ versions within hours. Analysts link it to the Shai-Hulud family from earlier in 2026.
Microsoft's anatomy, which gave the campaign the name ChainDrop, settled the open questions: evidence points to stolen maintainer credentials as initial access, and the propagation routine is brutally simple — download a package's latest tarball, copy the malware bundle in, add a loader, replace the lifecycle scripts, publish. One stolen token turns into malicious patch releases across every package that publisher can touch — Microsoft counted more than 400 packages across multiple unrelated publishers. Stolen data leaves encrypted with AES-256-GCM toward attacker HTTPS endpoints, with GitHub repositories as the fallback channel.
Aug 4
2026, ~09:00 UTC — first malicious release (keyv@6.0.0)
79–868+
package names poisoned (SafeDep verified → Aikido monitoring)
~727 KB
compiled preinstall payload; harvests keys, reads CI runner memory
2
IDE persistence vectors — Claude Code + VS Code hooks
The OrbitalReg defence
Developers and CI resolve against your OrbitalReg proxy, not
npmjs directly. A version published minutes ago isn't served
until it clears your remote-proxy policy — so a same-hour
poisoned keyv release is not automatically reachable
the instant it lands upstream.
Hold new upstream versions for N hours before serving them. This attack's whole advantage is speed; a quarantine window is the single control that most directly blunts a worm racing to propagate before advisories catch up.
Once the poisoned versions land in the OSV/advisory feeds,
every pull of an affected version through your registry gets a
403 instead of the
tarball — fleet-wide, from one policy change, without chasing
each project's lockfile.
The append-only trail answers "who pulled an affected version, when" in one query — the exposure list you need in the first hour of response. In air-gap mode, nothing new resolves at all until you explicitly import it.
preinstall script that ran
before anyone knew. The registry shrinks the blast radius and
speeds the response — it is not a force field. The controls that
matter just as much here are npm 12+ (which blocks unapproved
lifecycle scripts by default), lockfile pinning, and fast
credential rotation. And one postscript worth savouring:
Microsoft's own ChainDrop guidance now leads with npm v12's
min-release-age — the ecosystem itself has adopted
the cooldown model. That is exactly what patch-version quarantine
does, except enforced at the registry for every developer, every
CI runner and every format at once, instead of hoping each
machine's npm config has the flag set.
Indicators of compromise
IOCs as reported by Wiz, Socket, SafeDep and Aikido on 4 Aug 2026, extended with Microsoft's ChainDrop anatomy. Treat these as a starting point, not a complete list, and cross-check the sources below.
Sources
Related analysis: a similar install-time attack hit the Cargo
ecosystem weeks later — see
the Rust crates backdoor,
where malware ran during cargo build.
Exposed to this — or want to not be, next time?
Rico, the founder, walks through a proxy + quarantine + pull-gate layout for npm and your other formats — and what the audit trail gives you in the first hour of an incident like this one.