ChainDrop: how the self-propagating npm worm steals tokens and republishes itself
A Shai-Hulud-family worm turns one stolen npm token into poisoned releases of every package that publisher controls. What the advisories say, and what rotation and allowlisting limit.
Prakhar
Backend engineer · PressentifyPublished • Updated 6 November 2026

Singapore’s Cyber Security Agency (CSA) published advisory AD-2026-009 on 6 Aug 2026 about an active npm supply chain attack. Malicious versions of Keyv and related packages carry malware from the Shai-Hulud family, and CSA calls the campaign “ChainDrop”: a self-propagating variant.
It matters because the dangerous part is not the first poisoned package. It is that the payload steals the credentials of whoever installs it, then uses them to publish the next poisoned versions. Your build machine can become a distribution point.
What is confirmed, and by whom
Two primary sources carry this story. CSA’s advisory is the government notice. Microsoft Security Research (Ravikant Tiwari, Sagar Patil, Suriyaraj Natarajan) published a reverse-engineering analysis dated 4 Aug 2026 by its URL. Microsoft calls the payload a “Mini Shai-Hulud” variant: a self-spreading credential stealer shipped as a large, obfuscated Bun-based JavaScript bundle.
The two sources count scale in different units, so do not add them together. CSA reports more than 1,300 npm package versions compromised, with the affected packages totalling 2 billion monthly downloads. Microsoft reports more than 400 packages from multiple unrelated publishers, including keyv, flat-cache and cache-manager. CSA does not say how it counted, and its page shows a later update date than its publication date, so treat the figures as “as reported by CSA”.
What the download figure is not
The mechanism, step by step
- Run on install. Microsoft found that the malicious versions use a
preinstalllifecycle hook that runs a bundledsetup.mjs, which launches the Bun bundle before installation finishes. - Collect secrets. The payload gathers credentials from files, environment variables, shell histories, SSH keys, cloud config, CLI tools and GitHub Actions runner memory.
- Test what they reach. It checks access to npm, GitHub, AWS, Kubernetes and HashiCorp Vault, and pulls further secrets those identities can read.
- Republish. With an npm token it lists the packages the identity can write to, checks for write permission and the ability to bypass 2FA, downloads each package’s latest tarball, inserts the malware and a loader, replaces lifecycle scripts with the
preinstallhook, raises the patch version and publishes. - Send the loot out. The data is JSON, gzip-compressed, encrypted with AES-256-GCM, with the key wrapped using RSA-OAEP-SHA256.

Step four is the whole story. By Microsoft’s account, one stolen npm token can yield malicious patch releases across every package that publisher controls. The worm’s reach equals the token’s reach, which is why the scope of a token matters more than how many packages you personally maintain.
A second route that looks legitimate
Where the worm steals GitHub Actions OIDC publishing access, Microsoft says it publishes from a legitimate workflow identity, so those releases can carry valid provenance. Provenance tells you where a release was built, not that it is safe. Many other malicious versions had no matching source commit, pull request, tag or release; Microsoft concludes the attackers edited and published tarballs directly.

Worked example: one maintainer, one token
This is our own illustration, not an incident from the sources. Imagine a maintainer who publishes two small libraries and runs npm install on a laptop that holds a publish token. A poisoned dependency runs its hook, finds the token, and sees both libraries are writable. It republishes each with the patch number raised by one. Everyone who updates automatically now installs the worm, and each of them is the next maintainer in this story.
It also tries to stay on developer machines
Microsoft reports that the payload injects files into repository branches: .claude/settings.json, .claude/setup.mjs, .vscode/tasks.json and .vscode/setup.mjs. The aim is that later Claude or VS Code activity restarts the payload. Treat unexpected changes to editor and agent configuration files in review as seriously as changes to source. Related reading on how agent configuration becomes an attack surface: coding agents that disabled their own safety monitors.
Who did it: not established
On initial access, Microsoft says “Evidence points towards stolen maintainer credentials.” That is a hedged statement from a vendor, not a proven finding, and Microsoft names no threat actor. We do not name one either. Whether this is part of a confirmed lineage of earlier campaigns is also not verifiable from these two sources.
Fact versus vendor claim
What each control is recommended to limit
Neither source says any single measure stops the worm outright, and we do not either. Here is who recommends what.
- CSA: remove affected versions from development, build and CI/CD; treat affected systems as potentially compromised and rebuild them; rotate cloud credentials, GitHub tokens, SSH keys, Kubernetes configs, Terraform credentials and other secrets; review for unauthorised access; monitor indicators of compromise; and strengthen defences with dependency allowlisting, package integrity verification and provenance controls where available.
- Microsoft: upgrade to npm CLI v12 and use
min-release-age; check lockfiles, artifact repositories and CI caches, including transitive dependencies; pin known-good versions; purge npm and yarn caches; rotate credentials from a clean host; review token scopes, workflow approvals, protected environments and provenance; rebuild shared base images and golden runners.
Allowlisting is CSA’s recommendation only; Microsoft does not mention it and leans on pinning and release-age delay instead. The logic of each: rotation shrinks what a stolen token can still do, and an allowlist limits which versions can reach your build in the first place. Rotation done from a machine that is still infected hands the new secrets straight to the worm, which is why Microsoft says to rotate from a clean host.

Similar patterns appear in other cases we have covered: a credential-stealing release of a popular LLM library, a hostage token in an npm worm incident, and a breach where one API key set the blast radius. The common thread is that a credential’s reach decides the damage.
What to do now
- Check lockfiles, artifact repositories and CI caches, including transitive dependencies, against CSA’s notable list (keyv 6.0.0, flat-cache 6.1.24, file-entry-cache 11.1.6, cacheable-request 13.0.20, cacheable 2.5.1, cache-manager 7.2.10, ecto 5.0.1) and the full list CSA points to at Socket.dev.
- If you find one, treat that machine or runner as compromised, rebuild it, and rotate secrets from a clean host.
- Narrow npm token scopes and review workflow approvals and protected environments so one token cannot write to everything.
- Pin versions, delay brand-new releases with
min-release-age, and consider an allowlist for dependencies in build pipelines. - Review recent branches for the four injected
.claudeand.vscodefiles listed above.
Indicators such as the exfiltration domain and Ethereum RPC endpoints are in CSA’s advisory; we do not reproduce them in full. If you must reference the domain, write it defanged, as CSA does: npm-cache[.]com.
Sources & Credits
- Singapore CSA advisory AD-2026-009
- Microsoft Security Blog: ChainDrop supply chain compromise (4 Aug 2026)
Facts are from CSA advisory AD-2026-009 and Microsoft’s analysis; the diagrams, the one-maintainer illustration and the comparison of controls are our own work. Last verified 2026-11-05.
Share this article
Written by
Prakhar
Backend engineer · Pressentify
Backend engineer building Pressentify — interactive cheatsheets, handbooks and a job-hunt workspace.
Get the next one in your inbox
One practical backend article at a time. No spam; unsubscribe in one click.
Keep reading

Gemini API now stores your requests by default: audit your projects
Since 26 October 2026, new paid Gemini projects store requests for 55 days unless you say otherwise. What changed, what the docs say, and an audit script for call sites that never set store=false.
· 7 min

LiteLLM 1.107.0 was a credential stealer: how it got into the release workflow
A malicious LiteLLM 1.107.0 sat on PyPI for about 1h41m on 21 October 2026 and stole secrets at install time. The timeline, the release-workflow hole, and an audit you can run today.
· 8 min

Copilot drops Opus 4.8 and GPT-5.6 Terra on Nov 16, the API drops Sonnet 4.5 on Nov 30. Are you pinned?
Three retirement dates in the next 31 days, one of them already past for Gemini. A repo scanner for pinned model IDs, an eval gate that blocks regressions, and the order I would migrate in.
· 8 min