On August 4, 2026, a large-scale supply chain attack was recorded in the npm ecosystem: malicious code first discovered in [email protected] spread beyond the Keyv and Cacheable namespaces, impacting hundreds of packages across many organizations. The malware abuses the preinstall script mechanism to steal credentials from development and CI/CD environments, and then automatically republishes infected versions of other packages accessible via the stolen npm tokens. Any system that executed an infected version must be treated as compromised — and before rotating tokens you must first remove the credential revocation watcher installed by the malware, otherwise the rotation itself will trigger the attacker’s handler.
Scale of the campaign and divergent estimates
Estimates of the infection’s scale vary significantly between research groups. According to SafeDep, 353 malicious versions across 79 npm registry packages have been verified, while monitoring detected a broader spread — 442 versions in 353 packages. Aikido reports at least 868 packages and 1,381 infected versions. None of the higher estimates has been independently reproduced from a complete public list at the time of writing.
Crucially, all these numbers describe the count of malicious artifacts in the registry, not the number of compromised systems. Actual infection of a workstation or CI runner depends on whether a specific malicious version was resolved in the project’s dependencies and whether its lifecycle script executed.
Technical anatomy of the attack
Primary vector: npm package
The first confirmed malicious version was [email protected]. The package.json had a node setup.mjs command added as a preinstall hook, and the package included the files setup.mjs and Math_Symbol.js. The compiled library code itself remained unchanged — the package’s functionality was not disrupted, which made detection more difficult.
According to SafeDep, the first stage checks for the presence of the Bun runtime and, if necessary, downloads version 1.3.13 from the official GitHub releases, after which it hands off execution to a compiled bundle 727,680 bytes in size. This bundle collects a wide range of secrets:
- GitHub and npm tokens
- Cloud service credentials
- HashiCorp Vault and Kubernetes secrets
- Database connection details
- Private keys
- Contents of GitHub Actions runner memory
Socket independently confirmed the presence of functions in the code for modifying, versioning, and republishing packages on behalf of the stolen npm identity — this mechanism is what enables worm-like propagation.
Second vector: hooks in the repository
In addition to the npm package, an alternative execution path for the malicious code was found in the Keyv repository. The file .claude/settings.json contains a SessionStart hook that calls .vscode/setup.mjs. The file .vscode/tasks.json defines an “Environment Setup” task with the parameter runOn: folderOpen, which calls .claude/setup.mjs. The commit that introduced these hooks had the green GitHub verification badge and was signed on behalf of github-actions[bot]. The verified signature only confirms the validity of the cryptographic operation; it does not identify who controlled the credentials.
These hooks do not execute unconditionally. VS Code blocks automatic tasks in untrusted workspaces and prompts for confirmation by default. Claude Code applies a trust mechanism to settings supplied from the repository. However, a developer who habitually grants trust to a project will in doing so activate execution of the malicious code.
As of 17:40 IST on August 4, both hook files remained in the main branch, and core/keyv/package.json was still declaring version 6.0.0 with the malicious preinstall script.
Bypassing trust mechanisms
The infected Keyv release passed through a legitimate GitHub Actions workflow and received valid OpenID Connect (OIDC) and SLSA (Supply-chain Levels for Software Artifacts) attestations. The attestation correctly identified the build process but could not determine whether the source code entering that process was safe. This highlights a fundamental limitation: provenance and signatures verify the build path, but not the content of what was built.
Links to previous attacks
Semgrep documented identical Claude Code and VS Code hooks, the setup.mjs filename, and the download of Bun 1.3.13 in the April compromise of the lightning package on PyPI. Aikido attributes the August activity to the Shai-Hulud malware family. The artifact overlap confirms a connection at the malware-family level, but does not establish who is behind the August campaign — neither the initial access vector nor the specific actor has been identified.
Available data does not allow us to determine whether the worm spread solely from a single stolen publisher identity or whether independently compromised accounts of multiple developers were involved.
Impact assessment
All teams and organizations using Keyv, Cacheable, and related packages in their projects are at risk. Keyv is a popular library for unified access to data stores, widely used in the Node.js ecosystem. The compromise affects not only end applications, but also CI/CD pipelines where lifecycle scripts execute automatically.
Not all packages associated with the original maintainer were infected. According to SafeDep, published @keyv/* adapters and the Keyv 5.x line remained clean. However, the repository itself poses a separate risk: a subsequent commit placed malicious files into all 19 workspace packages, so any release built from the infected tree will contain malicious code.
Response recommendations
- Check your lockfiles (
package-lock.json,yarn.lock,pnpm-lock.yaml) for exact versions from the infected set. Do not rely on currentlatesttags — they changed over the course of the incident. At the time of observation, safe versions had been restored for a number of packages, including [email protected], [email protected], and [email protected]. - If an infected version was installed and executed, treat all credentials on that machine as compromised.
- Before rotating tokens, be sure to find and remove the credential revocation watcher installed by the malware. Rotating without removing the watcher can trigger the attacker’s handler.
- Upgrade your npm client to version 12, which blocks unapproved dependency lifecycle scripts by default. Earlier npm versions and alternative installation paths that allow lifecycle scripts remain vulnerable.
- Do not rely on namespace blocking alone as your only measure — this creates the risk of both missing infected versions and falsely blocking clean releases.
- Check your clones of the Keyv repository for the presence of
.claude/settings.jsonand.vscode/tasks.jsonfiles with malicious hooks. Do not grant trust to the workspace until the repository has been cleaned.
At the time of writing, neither the project maintainer nor npm nor GitHub had issued an official statement on the incident. Organizations using affected packages should immediately audit dependencies by exact versions from lockfiles, remove the malware’s watcher before any secret rotation, and migrate to npm 12 to protect against execution of unapproved dependency scripts — this mechanism was the key vector for the worm’s spread.