Shai-Hulud Worm Compromises 440+ npm Packages Including Keyv and Cacheable
A self-propagating infostealer worm dubbed Shai-Hulud has compromised over 440 npm packages — including widely-used libraries like keyv, cacheable, and flat-cache — collectively receiving more than 2 billion monthly downloads. The malware hijacks developer credentials to spread across the ecosystem and exfiltrates cloud secrets via GitHub.
Overview
A large-scale supply chain attack has hit the npm ecosystem. A threat actor operating under the name Shai-Hulud compromised the maintainer account behind the popular keyv and cacheable package families and published trojanized versions containing an infostealer worm.
The attack is notable for its self-propagating design — the malware steals npm credentials from infected developers and uses them to publish compromised versions of their packages, spreading laterally across the ecosystem without further attacker intervention.
Over 440 packages have been confirmed compromised, with a combined download count exceeding 2 billion per month. Many of these packages sit deep in dependency trees (e.g., eslint → file-entry-cache → flat-cache → keyv), meaning most affected developers never directly installed the compromised package.
The campaign was first tracked in September 2025, but escalated significantly in August 2026. OX Security published the initial broad analysis, while Socket's threat research team detected the malicious keyv@6.0.0 within six minutes of publication.
MITRE ATT&CK Kill Chain
This threat covers 11 of 14 attack phases. Highlighted phases indicate techniques actively used in this campaign.
Attack Breakdown
The attack begins when a developer installs a compromised package version. The trojanized package.json includes a preinstall lifecycle hook that triggers a file called setup.mjs.
This first-stage loader downloads a standalone Bun JavaScript runtime (v1.3.13) matched to the target platform. Using Bun instead of Node.js is a deliberate evasion technique — security tooling that monitors Node processes may miss it entirely. The loader then executes the second-stage payload: a heavily obfuscated ~728KB Bun bundle called Math_Symbol.js (or math_init.js in some variants).
The second stage is a modular infostealer with four internal components — [collector], [dispatcher], [provenance], and [publish] — using polymorphic basE91 encoding with per-scope alphabets to resist static analysis.
Credential harvesting is comprehensive: the malware sweeps for AWS credentials (including IMDS and Secrets Manager across regions), GCP service account keys, Azure client secrets, HashiCorp Vault tokens, Kubernetes service account tokens, GitHub Actions OIDC tokens, npm tokens, and generic secrets via regex patterns.
Exfiltration uses two channels. The primary method creates GitHub repositories via the API and commits AES-256-GCM encrypted data using GraphQL mutations. Repositories are tagged with the string "Shai-Hulud: Here We Go Again" — over 821 such repositories were identified at time of publication. A secondary channel resolves C2 destinations via DNS and transmits encrypted data directly.
Self-propagation is the most dangerous capability. The worm enumerates the victim's npm packages, downloads each tarball, injects the same malicious preinstall hook, recomputes integrity hashes, bumps the version, and republishes — all automatically. It even forges sigstore provenance by building DSSE attestation envelopes and submitting Rekor transparency log entries, making the trojanized packages appear legitimately signed.
Persistence is established through multiple mechanisms: macOS LaunchAgents, Linux systemd user services, and autostart hooks planted in .claude/settings.json and .vscode/tasks.json — targeting both human developers and AI coding agents.
The malware also includes a dead man's switch: a background service polls GitHub every 60 seconds with the stolen token, and if the token is revoked (HTTP 4xx), it executes a remote-supplied handler string via eval before self-destructing. An embedded warning string — "IfYouBlockThisAPIKeyItWillCrashTheLiveProductionServersOfAllThirdPartyClients" — is designed to dissuade developers from revoking compromised tokens.
Recommended Mitigations
Remove the dead man's switch before rotating credentials
The malware's persistence mechanism triggers destructive actions when tokens are revoked. Before rotating any credentials, locate and remove the background service: ~/Library/LaunchAgents/com.user.gh-token-monitor.plist on macOS, ~/.config/systemd/user/gh-token-monitor.service on Linux, and associated files under ~/.local/bin/ and ~/.config/gh-token-monitor/.
Remove installer artifacts and autostart hooks
Delete setup.mjs, Math_Symbol.js, math_init.js, and any bun-dl-* temp directories. Check .claude/settings.json and .vscode/tasks.json for injected autostart hooks that re-execute the payload when a developer or AI agent opens the project.
Rotate all credentials and tokens
After removing persistence mechanisms, revoke (not just rotate) all npm tokens, GitHub PATs, and GITHUB_TOKEN values. Rotate AWS, GCP, and Azure keys, Vault tokens, and Kubernetes service account tokens. Regenerate all CI/CD organization and repository secrets.
Pin and audit package versions
Downgrade affected packages to the last known-safe version before the compromise. Use exact version pinning with integrity hash verification. Block the keyv, @keyv, and cacheable scopes in your registry proxy until verified-clean versions are published. Audit npm accounts for unexpected package publications.
Update to npm v12 and restrict install scripts
npm v12 includes additional protections against malicious lifecycle scripts. Configure your environment to restrict or disable preinstall/postinstall script execution for untrusted packages. Consider using --ignore-scripts by default and explicitly allowlisting packages that require install scripts.
Monitor for indicators of compromise
Search GitHub for repositories tagged with "Shai-Hulud: Here We Go Again" associated with your organization's accounts. Check for outbound connections to AWS IMDS (169.254.169.254) and ECS credential endpoints (169.254.170.2) from development machines. Look for unexpected Bun runtime downloads from oven-sh/bun releases.
Awareness Response Kit
Train your team to recognize and respond to this specific threat with our interactive awareness game.