← Blog

keyv npm Attack: Shai-Hulud Worm Hits 400+ Packages

Share on X

August 4, 2026: Attackers compromised the GitHub and npm release path for maintainer jaredwray and published a malicious [email protected]—a key-value storage library with roughly 127 million weekly downloads. The same wave hit the related cacheable, flat-cache, and file-entry-cache family. Within hours a self-spreading Shai-Hulud worm had poisoned 400+ npm packages across unrelated organizations.

Researchers at Aikido, Socket, Snyk, JFrog, and SafeDep published technical analyses the same day. BreachHistory indexes the campaign at pkg-npm-keyv-cacheable-shai-hulud-202608.

What happened

This was not a typosquat. Attackers controlled the legitimate maintainer account, pushed malware into the jaredwray/keyv Git tree, and cut releases through the project's normal GitHub Actions workflow. Because the trojanized source was already in the tagged tree, [email protected] shipped with valid npm trusted-publishing provenance—a signed SLSA attestation that looked clean even though the tarball was malicious.

Socket's timeline (all times UTC, August 4):

  • 09:35[email protected] publishes; first confirmed package with the preinstall payload
  • ~09:41 — Socket flags the malicious hook (~six minutes later)
  • 09:38+ — worm republishes packages outside the keyv namespace (starting with @thiennq/docs-viewer)
  • 10:09–10:14 — burst across cacheable, flat-cache, file-entry-cache, cacheable-request, cache-manager, and @cacheable/*
  • Through the afternoon — mass republish into orgs including @ornikar, @deliveroo, @picsart, @qlik/@nebula.js, @onereach/@or-sdk, and @servicetitan

By mid-afternoon, Aikido counted at least 434 packages / 1,381 versions with multi-billion monthly install exposure in the dependency graph. SafeDep and Socket later tracked roughly 440–445 unique package names and more than 2,200 poisoned versions.

How the malware works

Every confirmed seed package adds two files and one lifecycle hook:

  • "preinstall": "node setup.mjs"
  • setup.mjs — dropper that downloads Bun 1.3.13 from the official GitHub releases if Bun is missing
  • Math_Symbol.js (seed packages) or math_init.js (worm republishes) — ~728 KB obfuscated second stage

Library dist/ code in [email protected] is byte-identical to the clean 6.0.0-rc.1 build. The package behaves normally after install while the host is already compromised. You do not need to import keyv for the payload to run—resolving and installing the affected version is enough on npm versions that still execute lifecycle scripts by default.

The second stage is a Shai-Hulud variant. Researchers recovered credential collectors for:

  • npm tokens (~/.npmrc and registry whoami validation)
  • GitHub PATs, App tokens, and Actions OIDC material—including runner memory scraping for secrets
  • AWS credentials and Secrets Manager, plus GCP/Azure key patterns
  • HashiCorp Vault tokens and Kubernetes service-account secrets
  • Stripe and Slack tokens, plus a broad filesystem regex sweep

Stolen bundles are encrypted and dumped to public GitHub repositories whose description contains "Shai-Hulud: Here We Go Again". Aikido observed a fallback C2 domain resolved through an Ethereum contract when GitHub upload fails.

Why it spread so fast

Shai-Hulud is a worm, not a one-shot trojan. When it finds an npm token with publish rights, it:

  1. Enumerates packages that token can write
  2. Downloads the current latest tarball
  3. Injects the same preinstall hook and payload files
  4. Bumps the patch version and republishes—often with freshly minted sigstore provenance

Separately, stolen GitHub tokens let the malware commit .claude/settings.json and .vscode/tasks.json autostart hooks. Opening an infected repo in VS Code—or starting a Claude Code session—can execute the loader without another npm install.

That combination is why household transitive packages matter. A common chain is eslintfile-entry-cacheflat-cachekeyv. Most victims never chose keyv directly; they inherited it.

Seed packages (confirmed first wave)

Scoped @keyv/* 6.0.0 adapters published minutes earlier without the hook should still be treated as suspect given the account compromise. Full version pins for hundreds of worm-republished packages are in the BreachHistory supply-chain manifest.

Who is at risk

Any developer laptop, CI runner, or build agent that installed an affected version and ran install scripts on August 4 (and subsequent worm republishes) should be treated as compromised. npm 12+ disables preinstall by default; many production pipelines still use older npm/Yarn/pnpm settings where lifecycle hooks execute.

This is a developer and CI secrets incident, not a consumer PII dump. The stakes are npm publish tokens, GitHub org access, cloud keys, and Vault/Kubernetes credentials that can open the next company.

Action items

  1. Audit lockfiles for the seed versions above and any unexpected patch bumps published August 4, 2026.
  2. Pin to last-known-clean releases (for example [email protected], [email protected]) and rebuild with integrity hashes—do not blindly npm update while the campaign is live.
  3. If install scripts ran: isolate the host, remove setup.mjs / Math_Symbol.js / math_init.js, and hunt for gh-token-monitor LaunchAgent/systemd persistence plus planted .claude/.vscode hooks.
  4. Rotate from a clean machine: npm tokens, GitHub PATs and Actions secrets, AWS/GCP/Azure keys, Vault tokens, Kubernetes service accounts, Stripe/Slack keys.
  5. Audit npm publish history for unexpected versions under your org scopes today.
  6. Search GitHub for new public repos or commits matching the campaign description string and for unauthorized chore: update config commits authored as Claude.
  7. Harden CI: prefer npm versions that skip lifecycle scripts by default, block unexpected Bun downloads, and require human review for trusted-publishing releases even when provenance verifies.

FAQ

Is this the same as the September 2025 Shai-Hulud worm?

Same family, new campaign. Researchers describe a Bun-loaded second stage, IDE/Claude autostart hooks, and GitHub dead-drop branding Shai-Hulud: Here We Go Again. It is distinct from the June 2026 Mastra / easy-day-js RAT and the March 2026 axios maintainer compromise.

Does valid provenance mean a package is safe?

No. Provenance proves which workflow built the artifact. If attackers already poisoned the source or release credentials, the attestation faithfully signs malware.

Are clean versions available?

Maintainers and npm removed or rolled back several seed releases during the incident. Registry state moved quickly—trust your lockfile pins and vendor advisories (including Snyk SNYK-JS-KEYV-18515941), not a casual latest tag check.

Canonical supply-chain record: keyv / cacheable Shai-Hulud August 2026 on BreachHistory.

Sources: Aikido, Socket, Socket campaign tracker, Snyk, JFrog, SafeDep, The Hacker News.

Updated 2026-08-05.