Keyv and friends compromised in active Shai-Hulud supply chain attack · Ilyas Makari, Aikido Security · aikido.dev, 4 August 2026
An npm worm shipped a Claude Code session-start hook alongside the install script
On 4 August an attacker took the GitHub account of the maintainer behind keyv,
a library Aikido puts at roughly 127 million weekly npm downloads, and pushed to
main before cutting releases. Every package in the family received setup.mjs
and Math_Symbol.js plus a "preinstall": "node setup.mjs" entry. The dropper
fetches Bun 1.3.13 and runs a 728 KB obfuscated bundle that harvests npm, GitHub,
AWS, Kubernetes, Vault, Stripe and Slack credentials, then republishes to
packages the stolen identity can reach. Aikido reported at least 434 packages
across 1,381 versions at 13:37 CEST; The Hacker News cites a later Aikido figure
of 868 packages and a SafeDep count of 353 verified poisoned versions across 79
names. The totals count artifacts, not machines, and were still moving.
The repository supplied a second execution path. Per The Hacker News, reading the
repository directly, .claude/settings.json carries a SessionStart
hook calling .vscode/setup.mjs, and .vscode/tasks.json carries an
Environment Setup task with runOn: folderOpen calling .claude/setup.mjs.
Each points into the other tool's directory, and both were still on main at
5:40 p.m. IST. Neither fires unconditionally: VS Code blocks automatic tasks in
an untrusted workspace, and Claude Code applies workspace trust to
repository-supplied project settings. Semgrep documented the same two hooks and
the same setup.mjs in an April compromise of the lightning PyPI package, so
this is a second sighting. The poisoned release also carried valid OIDC and SLSA
provenance, because it went through the project's real GitHub Actions workflow.
Why it matters: Your agent's configuration directory is executable. A
SessionStart hook is arbitrary code that runs when you open a session, so
"check out this repo and point your agent at it" and "run a stranger's script"
can be the same act. Check whether your install path still runs lifecycle
scripts, since npm 12 blocks unapproved ones by default and earlier clients do
not, and read .claude/ and .vscode/ in an unfamiliar checkout the way you
would read a Makefile you did not write. If you were hit, SafeDep advises
removing the credential-revocation watcher before rotating anything, because
revocation is what triggers it.