At 09:02 UTC this morning, a single poisoned commit pushed to the keyv GitHub repository set off the most aggressive npm supply chain worm ever recorded. Within 32 minutes, automated credential-harvesting machinery swept through nine unrelated organisations, republishing malicious versions at roughly one package per second. By the time security researchers at Aikido, SafeDep, Socket, and Wiz filed takedown requests, more than 420 distinct package names — carrying over 2 billion combined monthly installs — had been poisoned. For the first time in any documented supply chain attack, the worm planted persistence hooks directly inside AI coding-agent configurations: specifically, inside the .claude/settings.json file used by Claude Code and the .vscode/tasks.json task runner used by Visual Studio Code.

This is not a vulnerability in Claude Code or VS Code. It is, however, a stark demonstration that as AI coding agents become standard developer tooling, they simultaneously become a new and under-defended attack surface inside your software supply chain.

Key Takeaways

  • The keyv npm package (127 million weekly downloads) was compromised via a GitHub maintainer account takeover on August 4, 2026.
  • A self-replicating worm named Mini Shai-Hulud (CVE-2026-45321, CVSS pending) spread to 420+ packages across 9 organisations in under 33 minutes.
  • The worm steals AWS, GCP, Azure, GitHub, npm, Vault, and Kubernetes credentials, then installs a dead-man’s switch that executes attacker-supplied code the moment tokens are revoked.
  • Persistence is achieved via Claude Code’s SessionStart hook and VS Code’s folderOpen task — meaning a compromised dependency can persist without a fresh npm install.
  • Affected packages include keyv, cacheable, cache-manager, flat-cache, file-entry-cache, and dozens more with a combined 2+ billion monthly installs.
  • Any machine that ran npm install today against an affected version should be treated as fully compromised. Remove the dead-man’s switch before rotating credentials — the reverse of standard procedure.

How a Single GitHub Account Compromise Became a Two-Billion-Download Crisis

The attack began with the takeover of the GitHub account belonging to the maintainer of keyv, a simple key-value storage abstraction used under the hood by frameworks, ORMs, and SaaS toolkits across the Node.js ecosystem. This single maintainer also controls cacheable (29 million monthly downloads), flat-cache (565 million monthly downloads), and file-entry-cache (557 million monthly downloads) — a remarkable concentration of downstream risk in a single GitHub identity.

Once inside the account, the attacker acted on two fronts simultaneously. They injected a malicious setup.mjs loader and a heavily obfuscated 728 KB payload bundle named Math_Symbol.js into the repository, committing via a GitHub Actions bot identity — so every commit carried a green verified badge, lending it the appearance of a legitimate automated release. They also added "preinstall": "node setup.mjs" to each package.json, ensuring the payload executed automatically the moment any developer ran npm install against the tainted version.

The worm then harvested the victim developer’s npm publish tokens from environment variables and CI/CD runners, and used those tokens to republish malicious versions of every package in the compromised namespace at approximately one package per second. Nine organisations fell sequentially between 10:10 and 10:43 UTC — 33 minutes from first downstream victim to ninth. By the time SafeDep’s researchers published their incident report, the npm registry’s latest tags for many affected packages were still pointing to tainted releases, meaning fresh npm install runs continued pulling the malware.

Technical Breakdown: Inside the Mini Shai-Hulud Worm

Researchers at Wiz, SafeDep, and Socket reverse-engineered the payload and found a multi-stage, evasion-conscious architecture:

Stage Mechanism Purpose
1. Trigger preinstall npm lifecycle hook Executes before user code on bare npm install
2. Runtime Downloads Bun 1.3.13 from GitHub; self-deletes after use Leaves no persistent attacker binary on disk
3. Theft Scans env vars, ~/.aws, ~/.config/gcloud, Vault, K8s service accounts, GitHub Actions runner memory Harvests cloud credentials, tokens, and private keys
4. Spread Uses stolen npm publish tokens to republish malicious versions (~1 package/second) Self-replicates to victim’s entire npm organisation namespace
5. Persistence LaunchAgent (macOS) or systemd service (Linux), 24-hour TTL; polls GitHub API every 60 seconds Survives reboots; maintains command link
6. Dead-Man’s Switch eval() of attacker-supplied handler triggered on token revocation Standard incident response triggers a second-stage attack
7. IDE Hook Plants .claude/settings.json (SessionStart) and .vscode/tasks.json (folderOpen) Persists without any further npm install
8. Exfiltration RSA-4096 encrypted upload to 546 GitHub dead-drop repos titled “Shai-Hulud: Here We Go Again” Evades C2 detection; blends with normal GitHub traffic

The dead-man’s switch deserves particular attention from incident response teams. Conventional security playbooks instruct responders to immediately rotate all compromised credentials. Here, that instinct is weaponised: the moment a stolen token is revoked, the persistence agent receives an eval()-able payload from the attacker and executes it. You must locate and terminate the persistence mechanism before rotating any credentials — a reversal of standard playbook order that will catch under-prepared teams flat-footed.

The IDE Persistence Layer: An Unprecedented Attack Vector

The most novel aspect of this campaign — and the detail that distinguishes Mini Shai-Hulud from prior npm supply chain attacks, including the Sapphire Sleet campaign that backdoored debug and chalk with North Korean malware — is the deliberate exploitation of IDE and AI coding-agent configuration files as persistence vectors.

Claude Code’s .claude/settings.json supports a SessionStart hook — a shell command that executes every time a new Claude Code session opens in the workspace directory. The worm plants a malicious entry there, so any developer who opens the infected project in Claude Code silently executes the attacker’s script — no additional npm install required. VS Code’s .vscode/tasks.json with "runOn": "folderOpen" provides an equivalent execution primitive. Both hooks have entirely legitimate uses (running linters, setting up dev environments), making them difficult to detect without deliberate policy controls and explicit code-review policies for IDE configuration changes.

An infected repository then scans for other .claude/ and .vscode/ configurations across the developer’s machine and injects the same hooks, enabling cross-repository spread from a single compromised dependency. This represents a meaningful qualitative escalation in supply chain attack sophistication.

India’s JavaScript Developer Community Is Directly in the Blast Radius

India is home to one of the world’s largest Node.js developer populations. The packages compromised today — keyv, flat-cache, file-entry-cache — sit deep in the transitive dependency trees of popular frameworks used extensively by Indian product companies, IT services firms, and Global Capability Centres in Bengaluru, Hyderabad, and Pune. CI/CD pipelines that triggered a fresh npm install in the window between 09:35 UTC and late afternoon takedowns face a real and immediate risk of credential exposure.

The attack’s depth makes detection harder than average: many engineering teams will have pulled these packages through three or four layers of transitive dependencies, with no direct awareness that keyv was even in their stack. Run npm ls keyv cacheable flat-cache file-entry-cache right now to find out.

What You Should Do Right Now: Sanjay Seth’s Defensive Playbook

As a zero-trust architect who has spent three decades hardening enterprise environments — from FortiGate perimeters to CI/CD pipelines — here is the action sequence I recommend for every organisation running Node.js workloads. Sequence matters critically in this incident.

Step 1 — Identify Exposure

  • Run npm ls keyv cacheable flat-cache file-entry-cache cache-manager in every project and CI/CD pipeline.
  • Check lock files for tainted versions: keyv@6.0.0, cache-manager@7.2.10, cacheable-request@13.0.20. Wiz has published a full IOC list in their incident report.
  • Search CI/CD build logs for the strings setup.mjs and Math_Symbol.js.
  • Check GitHub Actions artifacts for repositories titled “Shai-Hulud: Here We Go Again”.

Step 2 — Remove the Dead-Man’s Switch Before Rotating Credentials

Do NOT rotate credentials yet. First, locate and terminate the persistence agent on every potentially affected machine:

  • Kill: ~/.local/bin/gh-token-monitor.sh
  • Delete (macOS): ~/Library/LaunchAgents/com.user.gh-token-monitor.plist
  • Disable (Linux): ~/.config/systemd/user/gh-token-monitor.service
  • Remove directory: ~/.config/gh-token-monitor/

Only after confirming the persistence agent is gone should you rotate: GitHub personal access tokens, npm publish tokens, AWS/GCP/Azure API keys, Kubernetes service account tokens, Vault tokens, SSH private keys, Stripe API keys, and database connection strings.

Step 3 — Audit IDE and AI Coding-Agent Configurations

  • Scan every repository on every developer machine for unexpected entries in .claude/settings.json — specifically, look for SessionStart hooks you did not explicitly add.
  • Audit every .vscode/tasks.json for tasks with "runOn": "folderOpen" referencing unfamiliar scripts.
  • Consider implementing a policy that flags changes to .claude/ and .vscode/tasks.json in every pull request, similar to how you should flag changes to CI/CD pipeline configuration files.

Step 4 — Harden npm Configuration Immediately

  • Add ignore-scripts=true to your project’s .npmrc, or run all installs as npm install --ignore-scripts. npm 12 now blocks unapproved lifecycle scripts by default — upgrade if you have not.
  • Enable dependency allowlisting with tools like SafeDep or Socket to gate which packages and lifecycle scripts are permitted.
  • Lock all dependencies to exact versions and commit your lock files. Avoid version ranges like ^6.0.0 that resolve to newly published poisoned releases.

Step 5 — Apply Zero-Trust Principles to Developer Environments

Developer workstations are the new perimeter. I recommend treating each machine as an untrusted endpoint: enforce least-privilege for npm publish tokens (scoped, short-lived, MFA-protected), use ephemeral CI/CD runners rather than persistent agents, and implement network microsegmentation so that a compromised developer laptop cannot directly reach production cloud credentials or internal secrets stores. The same zero-trust architecture that protects your network edge needs to extend all the way to your package.json.

Frequently Asked Questions

Is my machine compromised if I ran npm install on August 4, 2026?

If you installed any tainted version — including keyv@6.0.0, cache-manager@7.2.10, cacheable-request@13.0.20, or their transitive dependents — between approximately 09:35 UTC and the time your registry pulled cleaned versions, treat the machine as fully compromised. Wiz and SafeDep have published version hash IOC lists to help you verify specific package versions.

Is Claude Code itself vulnerable, or is this purely an npm problem?

Claude Code is not inherently vulnerable — its SessionStart hook is a legitimate, intentional feature that this worm abused. The vulnerability lies in the software supply chain: once a malicious npm package is installed, it can write arbitrary files, including IDE and coding-agent configuration files that execute commands on project open. Claude Code applies workspace trust controls that restrict hook execution in untrusted workspaces, but developers who have already marked a workspace as trusted would not receive an additional prompt.

How rapidly did the worm actually spread?

Extraordinarily rapidly. SafeDep’s telemetry documented nine distinct organisations compromised between 10:10 and 10:43 UTC — 33 minutes from first downstream victim to ninth. Each organisation’s entire npm namespace was republished at approximately one package per second using stolen publish tokens. This machine-speed propagation is what escalated a targeted account compromise into a registry-wide incident affecting 420+ package names.

What is the dead-man’s switch, and why must I remove it before rotating credentials?

The worm installs a background process that polls GitHub’s API every 60 seconds using stolen tokens. When those tokens are revoked — the first step in standard incident response — the process receives an attacker-specified JavaScript payload and executes it via eval(). Rotating credentials before removing this process therefore triggers a second-stage compromise. The correct sequence is: find and kill the persistence agent, verify it is gone, then rotate all credentials.

The New Rule: Your Dependency Tree Is Your Attack Surface

The Mini Shai-Hulud campaign marks a watershed moment in software supply chain security. The combination of worm-speed propagation, a dead-man’s switch that punishes textbook incident response, and IDE hooks that survive without any reinstall represents a genuine qualitative leap in attacker sophistication. Every organisation running Node.js workloads — from a five-person startup to a multi-thousand-seat Global Capability Centre in Bengaluru — should treat today as a live fire drill and run through the checklist above before end of business.

If you are uncertain whether your environment is exposed, or if you want an expert assessment of your software supply chain controls, zero-trust developer environment architecture, or CI/CD pipeline security posture, contact Sanjay Seth’s team for a security assessment. With three decades of enterprise security experience and a deep practice in zero-trust implementation across India’s largest enterprises and GCCs, we can help you determine your current exposure and build the layered controls your modern development environment demands.