Aiignitions
Tech News

Self-Replicating npm Worm Poisons Keyv and 440+ Packages

A self-replicating npm worm compromised keyv and 440+ packages on August 4, 2026, stealing cloud and CI credentials. What happened and how to respond.

Self-Replicating npm Worm Poisons Keyv and 440+ Packages

What happened

On August 4, 2026 someone took over the GitHub account that maintains keyv and the wider cacheable family of caching libraries, then pushed a poisoned release. The first confirmed malicious version was [email protected]. From there it spread on its own.

Security firm SafeDep, which tracked the campaign minute by minute, logged the release commit at 09:02 UTC and the first poisoned npm publish about half an hour later. By 13:18 UTC the same payload had reached a final target across twelve organizations. Its confirmed footprint, as of August 5, 2026: 2,234 poisoned package versions across 444 package names. Counts differed between trackers as the wave was still moving. Socket and Aikido, who published their own analyses the same day, reported smaller numbers earlier in the day.

The npm logo. keyv is published on the npm registry, which the worm used to republish itself.

The malware is a variant of Shai-Hulud, a self-propagating npm worm researchers have tied to earlier 2026 compromises. It steals credentials on install and then uses whatever npm publishing tokens it finds to poison more packages. That is what turns a single account takeover into a fast-moving outbreak.

Why it matters

keyv is not an obscure package. It pulls roughly 127 million downloads a week, and two of the compromised siblings, flat-cache and file-entry-cache, sit underneath ESLint. That places the malicious code inside the dependency tree of projects that never installed keyv directly and have no obvious reason to think of it.

The blast radius is anyone who ran npm install in the window, on a laptop or in CI. SafeDep put the combined reach of the largest affected packages at well over a billion monthly downloads. When a package this deep in the tree ships a credential stealer, the question is not who is affected but who can prove they are not.

A GitHub search for Shai-Hulud returning about 3,000 repositories, showing the scale of the worm's exfiltration infrastructure.

The scoped @keyv/* adapter packages and the keyv 5.x line were not touched, so not every keyv user was hit. The damage lands on projects that resolved to the poisoned 6.x releases or their compromised dependents.

How the worm spreads

The mechanism is old and reliable: a lifecycle script. The attacker added a single line to package.json, a preinstall hook that runs "node setup.mjs" before any of your own code executes. On install, setup.mjs downloads a copy of the Bun runtime from GitHub's official releases and uses it to run a second file, a 727KB compiled bundle that does the actual work.

That bundle sweeps the machine for secrets: GitHub tokens, npm tokens, AWS keys, Google Cloud service accounts, Azure credentials, Stripe keys, database connection strings, private-key blocks, Vault tokens, and Kubernetes service-account tokens. In CI it goes further, reading GitHub Actions secrets straight out of runner memory and planting a workflow that dumps the repository's secrets into a build artifact.

Stolen npm publish tokens are the fuel. The same byte-identical payload reappeared across unrelated organizations every few minutes, which SafeDep reads as automated propagation driven by harvested tokens rather than a dozen separate break-ins. One poisoned release even carried valid SLSA provenance pointing at the real release tag. The signature was genuine; it just proved that legitimate infrastructure had built compromised source.

The Claude Code and VS Code twist

The install hook is the loud part. The quieter part is what the attacker left in the repository itself. The poisoned source shipped a .claude/settings.json with a SessionStart hook and a .vscode/tasks.json task set to run on folder open. Open the project in Claude Code or VS Code and the payload gets a second chance to execute, this time with nothing in your lockfile to give it away.

The GitHub logo. The attacker seized a maintainer's GitHub account and hid execution hooks inside the repository's editor config.

Both hooks need the editor's workspace-trust prompt to fire, so they are not fully automatic. But they show where supply-chain attacks are heading. AI coding agents and editors run project-defined tasks on your behalf, and a credential stealer that hides in editor config is invisible to the dependency scanners everyone now points at package.json.

The dead-man's switch

The payload does not simply grab tokens and leave. It installs a watcher that polls GitHub every 60 seconds with a stolen token. The moment that token is revoked and the request starts failing, the watcher runs attacker-supplied code. It survives a reboot as a macOS LaunchAgent or a Linux systemd user service, and on Linux it enables lingering so it keeps running after logout.

This detail rewrites the incident-response playbook. The instinct after a token leak is to rotate everything immediately. Here, rotating first can be the trigger that fires the handler. SafeDep's guidance is blunt: find and remove the watcher before you revoke anything.

What to do now

If you or your CI ran npm install against these packages during the window, treat the environment as compromised and work in this order:

  • Hunt before you rotate. Look for the watcher's files, a gh-token-monitor script and config under your home directory, plus the LaunchAgent (macOS) or systemd user service (Linux). Remove it first, then rotate credentials.
  • Assume CI tokens leaked. Any npm, GitHub, or cloud token exposed to a build in the window should be rotated after the watcher is gone.
  • Check your lockfile. Compare resolved versions against the published affected-package lists. keyv 5.x and the scoped @keyv/* adapters are clean.
  • Turn off install scripts in CI. npm 12 and later block unapproved dependency lifecycle scripts by default; older clients still run them. Pin the version or disable scripts outright.
  • Sweep the repo, not just the tree. Grep for the injected editor hooks and the secret-dumping workflow. A clean lockfile does not clear the .claude and .vscode config.
A second GitHub search showing hundreds of Shai-Hulud dead-drop repositories used to exfiltrate stolen credentials.

What's next

By the end of August 4 the community had begun pulling poisoned versions and revoking tokens, and npm's default script-blocking in newer clients kept many machines from ever running the payload. The initial access path, how the maintainer's account was taken over in the first place, had not been pinned down as of August 5, 2026, and no actor has been named.

The takeaway is not that keyv was uniquely careless. It is that one account with publish rights to a widely depended-on package is enough to reach a billion downloads in an afternoon, and the newest wrinkle, execution hooks aimed at AI coding tools, sits in a place most defenses are not yet looking. Enforce two-factor and trusted publishing on maintainer accounts, disable install scripts in CI by default, and scan the whole repository rather than the dependency manifest alone.

Read the original source

Head to the original source for the full announcement and complete details.

Read Original Source