The keyv worm ate 400+ npm packages in 90 minutes — check if you're exposed
Two weeks ago, on August 4 at 09:00 UTC , an attacker compromised a single maintainer's GitHub account and turned keyv — a caching library with 150M+ weekly downloads — into a self-replicating credential-stealing worm. Within 90 minutes it had spread to 400+ packages , including cacheable, cache-manager, cacheable-request, and ecto. The worm even signs off in its own fallback C2 marker: "Shai-Hulud: Here We Go Again."<br>If you ran npm install on the wrong afternoon, the malware went looking for your AWS keys, GitHub tokens, SSH keys, Kubernetes secrets, HashiCorp Vault stores, crypto keystores — and, notably, your AI agent configs (Claude, OpenAI, Cursor, Gemini, Codex). Then it used any npm tokens it found to republish itself into your packages, bypass_2fa: true. That's the "worm" part.<br>What made this one different<br>This wasn't a nuisance crypto-miner. Three things stand out:<br>It self-propagates. Stolen npm tokens → inject payload → bump patch version → republish. One compromise becomes 400.<br>It targets AI-agent infrastructure. It establishes persistence via Claude Code hooks (.claude/settings.json) and VS Code tasks (.vscode/tasks.json), and steals AI-agent credentials directly. If you've got coding agents installing dependencies unattended, this is aimed at you.<br>It forged provenance. In the right GitHub Actions context it generated valid SLSA provenance attestations binding malicious source to packages — so "verified provenance" alone wouldn't have saved you.<br>Are you exposed? Check now (2 minutes)<br>Fast grep — look for the payload and persistence artifacts:<br># The stage-two payload file<br>find . -path '*/node_modules/keyv/Math_Symbol.js'
# Persistence hooks the worm writes<br>grep -rl "_NODE_RUNTIME_INIT" . 2>/dev/null<br>find . -name 'setup.mjs' -path '*node_modules*'
# Known-bad file hashes (SHA-256)<br># math_init.js 9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc<br># setup.mjs fd3ca4007b225fdf8de7af4345a19179d5efa8c4bb9205f88cda806e5684b1eb<br>Network IOCs to block/hunt: npm-cache[.]com, js-mirror[.]com, pypi-get[.]com, and a C2 dead-drop resolved via an Ethereum contract. A suspicious User-Agent: Bun/1.3.13 and /tmp/bun-dl-*/ directories are also tells.<br>Known-bad versions include: keyv@6.0.0, cacheable-request@13.0.20, cache-manager@7.2.10, ecto@5.0.1, plus nine cacheable-family versions and 400+ others.<br>Or just scan it: paste your repo into InstallSafe /scan and it'll flag any compromised keyv-family versions (and every other known-malicious or vulnerable version) in your dependency tree using live OSV.dev advisory data. Free, no signup, nothing installed.<br>If you're hit<br>Treat the machine as compromised — rebuild CI runners and dev boxes that installed affected versions.<br>Rotate everything : cloud keys, GitHub/npm tokens, SSH keys, and any AI-agent API keys.<br>Remove the .claude/settings.json and .vscode/tasks.json persistence hooks.<br>Audit npm for packages you publish — the worm may have republished them.<br>The uncomfortable lesson: scanning after the fact is losing<br>Every defense that runs after npm install — CVE scanners, SBOM diffs, post-hoc audits — lost this race. The worm stole your secrets during the install lifecycle script, before any dashboard lit up red. Even provenance checks got forged.<br>The only defense that structurally works is blocking bad versions at the install boundary, before npm ever fetches them. That's the entire premise of InstallSafe — a drop-in npm registry proxy that filters known-malicious and vulnerable versions using live OSV.dev data, so the compromised tarball never reaches your machine. One config line, byte-for-byte tarballs (your lockfile hashes stay valid), works with npm/yarn/pnpm/bun and CI:<br>npm config set registry https://r.installsafe.ioIt won't catch a zero-hour compromise the instant it's published — nothing purely advisory-based can — but it slams the door on every version the moment it's flagged, across your whole org and every CI runner, with zero workflow change. And if you've got AI agents installing dependencies unattended — the exact target of this worm — a firewall at the registry is the one place you can actually govern what they pull.<br>Start with the free scan. Find out if the worm's already in your tree: installsafe.io/scan<br>Sources: Wiz, Datadog Security Labs.
Previous<br>Best SCA Tools 2026: Compare Top Solutions
Share
Powered by Ghost