keyv / cacheable npm worm ('ChainDrop') — Shai-Hulud-lineage credential stealer plants Claude Code + VS Code auto-run hooks (Aug 2026)
TL;DR
An attacker compromised the GitHub maintainer account behind keyv and its sibling @cacheable-family caching packages (a combined dependency tree with hundreds of millions of downloads) and published poisoned releases carrying a Shai-Hulud-lineage credential-stealing worm — the same release also planted .claude/settings.json and .vscode/tasks.json auto-run hooks in affected repos. Microsoft's own Security Blog has since named the campaign "ChainDrop" and confirmed it spread to 400+ packages across multiple, unrelated publisher accounts — not just the original keyv/cacheable maintainer — via stolen npm tokens propagating the worm publisher-to-publisher. Package/version counts climbed for the first ~48 hours before stabilizing; as of this update, still no single official "fixed" release exists — pin to a version predating 2026-08-04 rather than trusting latest.
What happened
Starting around 2026-08-03 15:00 UTC, Wiz observed C2-resolution traffic to public Ethereum RPC nodes tied to this campaign; at 2026-08-04 ~09:00 UTC, the attacker used a compromised GitHub maintainer account to push malicious commits directly to the keyv repository's default branch and cut a new release, keyv@6.0.0 (Aikido; Wiz). The same maintainer account owns a cluster of related caching packages — cache-manager, cacheable-request, flat-cache, file-entry-cache, cacheable, @cacheable/memory, @cacheable/node-cache, @cacheable/utils, @cacheable/net — all of which received poisoned releases in the same window.
Two distinct payload mechanisms shipped together:
- npm install-time credential stealer. The poisoned
package.jsonadds"preinstall": "node setup.mjs".setup.mjsis an obfuscated dropper that checks for the Bun JavaScript runtime, downloads Bun 1.3.13 if absent, and hands off to a ~728 KB compiled bundle (Math_Symbol.js/math_init.js) that harvests npm tokens (~/.npmrc, validated against the registry before exfiltration), GitHub tokens (classic PATs, OAuth, GitHub App, JWT/OIDC — including reading GitHub Actions runner memory), AWS credentials (config files, env vars, EC2/ECS instance-metadata, cross-region Secrets Manager enumeration), Kubernetes service-account tokens, HashiCorp Vault tokens, Stripe/Slack tokens, and roughly 200 glob patterns covering.envfiles, SSH keys, Terraform state, Docker configs, IDE settings, and VPN configs. Files over 5 MB are skipped; the harvester runs up to 64 concurrent reads. - AI-agent config auto-run hooks (planted in affected repos, not the npm registry). The same compromised-maintainer commit added
.claude/settings.jsonwith aSessionStarthook invoking.vscode/setup.mjs, and.vscode/tasks.jsonwith an"Environment Setup"task set torunOn: folderOpeninvoking.claude/setup.mjs— a cross-triggering pair, so opening the repo in either Claude Code or VS Code can fire the other tool's copy of the payload (The Hacker News). This is the same "AI coding tool auto-executes workspace config on open" root cause this repo already tracks for Claude Code, Cursor, Windsurf, and Amazon Q — VS Code and Claude Code both gate automatic tasks/hooks behind workspace-trust by default, so a trusted-workspace click is still required, but any repo a developer has already trusted (a fork, a clone of a popular package) is exposed the moment it's reopened.
Scale is still moving and sources disagree. SafeDep verified 353 poisoned versions across 79 package names at time of reporting (via The Hacker News); Aikido's later count put it at "at least 868 packages across 1,381 versions"; OX Security reported "+440 packages"; combined download-volume estimates across all cited sources exceed 2 billion monthly installs. Weekly/monthly download figures for keyv itself also vary by source (127M weekly per one report vs. 604M monthly per another) — stated here as reported rather than picked, per this repo's accuracy bar; treat both as rough orders of magnitude, not precise counts, while the incident is still active.
Exfiltration and C2. Stolen credentials are encrypted (readable only with the attacker's RSA private key) and uploaded to newly created public GitHub repositories whose description contains the string "Shai-Hulud: Here We Go Again" — Wiz counted 546 such repos created on 2026-08-04 alone; other sources report figures approaching 1,300. A fallback C2 channel resolves through the domain npm-cache[.]com (registered 2026-05-22, currently resolving via Cloudflare), with pypi-get[.]com and js-mirror[.]com also observed. Wiz additionally documented the malware querying public Ethereum RPC endpoints (eth-mainnet.nodereal[.]io, go.getblock[.]io, eth.llamarpc[.]com) to resolve C2 configuration from an on-chain smart contract, funded from a wallet address previously flagged for scam activity — the same blockchain-dead-drop resilience pattern this repo already tracks for Solana-memo and Ethereum-based C2 in other 2026 campaigns.
Provenance abuse. The poisoned releases carried valid OIDC and SLSA provenance, published through the legitimate GitHub Actions release pipeline, and the commit that planted the .claude/.vscode hooks carried a green GitHub-verified badge with github-actions[bot] as the listed author. As this repo has noted before: a verified-provenance badge proves who ran the pipeline, not that the artifact is safe — here it proves the attacker's pipeline ran, using the maintainer's stolen credentials.
Attribution. Researchers describe the malware as a descendant of the "Mini" Shai-Hulud family with code/infrastructure similarities to the TeamPCP and antv (self-minted Sigstore attestation) campaigns already tracked in this repo, and note the same IDE-hook mechanism appeared in an April 2026 PyPI (lightning) compromise. No named actor or initial-access vector for the maintainer account itself has been confirmed as of this writing.
No official patched version has been published by the maintainers, npm, or GitHub as of this writing. latest tags on affected packages may still resolve to a malicious version — pin to a known-good version predating this incident rather than trusting latest.
Update (2026-08-06) — "ChainDrop," and confirmation the worm spread beyond the original maintainer account. Microsoft's Security Blog published its own technical analysis on 2026-08-04, naming the campaign ChainDrop and confirming it as a self-propagating worm: "one stolen [npm] token can produce malicious patch releases across every package available to that publisher," and Microsoft's own count puts the confirmed scope at more than 400 packages compromised across multiple unrelated publisher accounts — i.e., the worm didn't stay contained to the keyv/@cacheable maintainer's own packages, it used stolen tokens harvested from early victims to poison further, unrelated publishers' packages in turn. Microsoft's writeup adds two technical details not in the original reporting: the credential-harvesting payload encrypts stolen data with AES-256-GCM before exfiltration, and Microsoft's recommended mitigation is to update to npm CLI v12 (which defaults to blocking unapproved lifecycle scripts) and to enable the min-release-age setting so a freshly-published version of any dependency isn't installed until it's had time to be flagged. Combined download-volume estimates across all cited sources (Aikido, Wiz, Microsoft) remain in the ~2 billion monthly installs range for the affected package set as a whole.
Update (2026-08-08) — maintainer account named, government advisory issued, lineage confirmed to April 2026 PyPI compromise. Multiple independent writeups (Chainguard, corroborated by SC Media) now publicly name the compromised account as belonging to Jared Wray (jaredwray), maintainer of record for the keyv/cacheable package family. Chainguard's technical analysis traces the identical setup.mjs filename, Bun 1.3.13 staging path, and hook-file structure directly back to the April 2026 PyTorch Lightning PyPI compromise and the May 2026 @antv npm wave (both already tracked in this repo), confirming this is the third documented wave of the same toolkit lineage rather than an independently-developed payload. Singapore's Cyber Security Agency (CSA) issued a public advisory on the campaign (AD-2026-009) — the first government-body advisory this repo has tracked for a keyv/cacheable-lineage incident. No official "clean" release has still been announced as of this update; continue pinning to a pre-2026-08-04 version.
Am I affected?
# Check installed versions against the packages named in this incident
npm ls keyv cache-manager cacheable-request flat-cache file-entry-cache cacheable \
@cacheable/memory @cacheable/node-cache @cacheable/utils @cacheable/net 2>/dev/null
# keyv@6.0.0 and cache-manager@7.2.10 / cacheable-request@13.0.20 / @cacheable/utils@2.5.1
# are confirmed-malicious releases per Wiz's published IOC list:
# https://github.com/wiz-sec-public/wiz-research-iocs/blob/main/reports/keyv-packages.csv
# Look for the dropper and payload files this campaign plants
find . -path '*/node_modules/*' \( -name 'setup.mjs' -o -name 'Math_Symbol.js' -o -name 'math_init.js' \) 2>/dev/null
# Check for the planted AI-agent auto-run hooks in YOUR OWN repos (not node_modules) —
# this is the part that persists even after you remove the bad package
grep -l "SessionStart" .claude/settings.json 2>/dev/null
grep -l "folderOpen" .vscode/tasks.json 2>/dev/null
# Look for the exfil GitHub-repo marker if you suspect you were a source of stolen creds
# (search github.com for repos you don't recognize with this description string)
# "Shai-Hulud: Here We Go Again"
If any of the above match, treat every credential the affected machine or CI runner had access to as compromised — npm tokens, GitHub tokens/PATs, AWS/GCP/Azure credentials, Kubernetes service-account tokens, Vault tokens, Stripe/Slack tokens, SSH keys, and any .env secrets.
If you are affected
- Remove the affected package versions immediately; do not simply re-run
npm installagainstlatestuntil a confirmed-clean version is announced — pin to a version predating 2026-08-04. - Treat any machine or CI runner that installed an affected version as fully compromised; rebuild rather than clean in place.
- Delete the planted
.claude/settings.jsonSessionStarthook and.vscode/tasks.jsonfolderOpentask if found, and diff them against your last known-good commit before trusting the workspace again. - Rotate every credential class listed above, in priority order (npm and GitHub tokens first, since those enable further propagation).
→ playbooks/if-you-installed-a-bad-npm-package.md → playbooks/if-you-ran-malicious-postinstall.md → playbooks/rotating-cloud-credentials.md → playbooks/if-your-npm-token-leaked.md → playbooks/if-your-github-pat-leaked.md
Prevention
→ prevention/npm-hardening.md — pin exact versions, avoid latest/floating ranges, use lockfiles with integrity hashes.
→ prevention/supply-chain-attack-surface.md
- Diff .claude/, .vscode/tasks.json, AGENTS.md, and other agent-config files on every dependency-tree change, the same way you'd review a package.json diff — this campaign proves the two are now the same threat surface.
- A green "provenance verified" badge on an npm release confirms the publishing pipeline ran, not that the artifact is safe; it does not substitute for pinning known-good versions.
- npm ≥ 12 blocks unapproved dependency lifecycle scripts by default (allowScripts: off) — upgrade if you haven't; earlier npm clients remain exposed to the preinstall vector used here.
Sources
- Aikido Security — Keyv and friends compromised in npm supply chain attack — primary technical writeup: payload structure, credential targets, exfil GitHub-repo marker, IOC hashes.
- The Hacker News — Keyv-Linked npm Worm Poisons Hundreds of Packages, Plants Claude Code and VS Code Hooks — SafeDep-sourced version/package counts,
.claude/.vscodehook mechanism and workspace-trust caveat, provenance-abuse detail. - Wiz — keyv and cacheable npm Package Hijacked in Supply Chain Attack — timeline, Ethereum RPC C2 resolution, C2 domain IOCs, campaign attribution/lineage, IOC hash list (github.com/wiz-sec-public/wiz-research-iocs).
- Microsoft Security Blog — ChainDrop supply chain compromise: Anatomy of a self-propagating worm — vendor naming ("ChainDrop"), 400+ packages across multiple unrelated publishers, AES-256-GCM exfil detail, npm v12 /
min-release-agemitigation guidance. - Chainguard — The keyv and cacheable npm Supply Chain Attack: Inside the Mini Shai-Hulud Campaign — names the compromised maintainer account, traces toolkit lineage to the April 2026 PyTorch Lightning and May 2026 @antv compromises.
- Cyber Security Agency of Singapore — Ongoing npm Supply Chain Attack Affecting Keyv and Related Packages ("Shai-Hulud" Worm), AD-2026-009 — first government-body advisory tracked for this incident.