Best Tech & Security Platform
Followed by 1000+

GEANTECHNOLOGY

Your Trusted Source for IT Tutorials and Tech Insights

The Keyv npm Worm: How a Single Compromised Account Poisoned Hundreds of Packages (And What You Should Do Right Now)

Aug 4, 2026 ahmed mokdad 12 min read
The Keyv npm Worm: How a Single Compromised Account Poisoned Hundreds of Packages (And What You Should Do Right Now)

On August 4, 2026, attackers compromised the GitHub account behind Keyv, a key-value storage library trusted by millions of developers. Within hours, a self-spreading worm hijacked the npm registry, infecting hundreds of packages and stealing credentials from developer machines and CI pipelines. This post breaks down exactly what happened, why provenance signatures failed to stop it, and how you can protect your projects.

Note : “If you installed any package from the Keyv, Cacheable, or flat-cache families on August 4, 2026, treat your machine as compromised. Rotate every credential that touched that environment, remove the malware’s persistence hooks before revoking tokens, and audit your dependency lockfiles immediately.”

Table of Contents

  1. What Is the Keyv npm Worm?
  2. How the Attack Unfolded
  3. The Payload: What It Steals and How It Spreads
  4. The Hidden Danger: IDE and AI Assistant Hooks
  5. Why Provenance Signatures Did Not Help
  6. The Bigger Picture: A Pattern of npm Worms
  7. Immediate Steps to Protect Your Projects
  8. How to Clean Up After Exposure
  9. Building Long-Term Supply Chain Resilience
  10. Conclusion

What Is the Keyv npm Worm?

Keyv serves as a lightweight key-value storage abstraction for Node.js. It pulls roughly 127 million weekly downloads, and the same maintainer controls an entire family of caching utilities including cacheable, flat-cache, file-entry-cache, and cache-manager. Together, these packages rack up over two billion monthly installs.

On August 4, 2026, attackers seized the maintainer’s GitHub account. They pushed malicious files directly to the main branch, cut new releases, and published poisoned versions to npm. The first confirmed malicious release was keyv@6.0.0. It added a preinstall script, bundled two new files named setup.mjs and Math_Symbol.js, and left the actual library code untouched.

The worm belongs to the Shai-Hulud malware family, a lineage of self-propagating npm threats that first surfaced in September 2025. Security researchers at SafeDep, Socket, Aikido, and Wiz all tracked the August campaign. SafeDep verified 353 poisoned versions across 79 package names. Aikido later reported at least 868 packages across 1,381 versions. The numbers shifted rapidly because the worm kept spreading.

A laptop screen displays source code with a padlock icon, symbolizing software supply chain security

How the Attack Unfolded

The Initial Compromise

The attacker gained control of the maintainer’s GitHub account. Researchers have not publicly identified the exact entry point, but phishing remains the most common vector for these attacks. The compromised account gave the attacker push access to every repository the maintainer owned.

At 9:00 UTC on August 4, the attacker introduced IDE persistence payloads into the Keyv repository. Shortly after, they published keyv@6.0.0 with the malicious preinstall hook. The release passed through the project’s legitimate GitHub Actions workflow, which meant it carried valid OpenID Connect (OIDC) and SLSA provenance attestations.

The Spread Beyond Keyv

The worm did not stay inside the Keyv family. It harvested npm publish tokens from infected machines and used them to poison packages belonging to other maintainers. Within hours, the compromise reached major organizations including Deliveroo, Picsart, Qlik, and OneReach.

SafeDep observed whole-namespace publishing bursts that pointed to automated propagation. The attacker did not need to manually log into each account. The malware did the work once it found valid credentials.

The Payload: What It Steals and How It Spreads

Stage One: The Dropper

The preinstall hook runs node setup.mjs before the npm install completes. This file is a heavily obfuscated dropper. It checks whether the Bun JavaScript runtime is present. If not, it downloads Bun version 1.3.13 from the official GitHub releases page.

The dropper then hands control to Math_Symbol.js, a 728 KB compiled bundle. Using Bun instead of Node helps the payload evade some runtime detections and gives the attacker a consistent execution environment across targets.

Stage Two: The Credential Harvester

SafeDep’s analysis shows that Math_Symbol.js targets a wide range of secrets. It reads GitHub tokens, npm authentication tokens, cloud provider credentials, HashiCorp Vault secrets, Kubernetes service-account tokens, database connection strings, and SSH private keys.

The payload also reads GitHub Actions runner memory directly. This technique bypasses log masking and lets the malware steal CI secrets that the runner holds in RAM. Socket separately decoded code for modifying, versioning, and republishing packages from any stolen npm identity.

Stage Three: Exfiltration and Propagation

The malware encrypts stolen data and exfiltrates it to attacker-controlled GitHub repositories. Wiz researchers noted that these repositories carry the description “Shai-Hulud: Here We Go Again.” The payload also installs a token-revocation watcher.

This watcher is particularly nasty. It monitors whether you revoke exposed credentials. If you rotate a token before removing the watcher, the malware triggers an attacker-supplied local handler. SafeDep explicitly warns responders to remove this watcher before rotating any tokens or keys.

The Hidden Danger: IDE and AI Assistant Hooks

The repository carries a second execution path that many defenders overlook. The attacker planted Claude Code and Visual Studio Code hooks inside the repository itself.

The .claude/settings.json file contains a SessionStart hook that calls .vscode/setup.mjs. The .vscode/tasks.json file contains an Environment Setup task with runOn: folderOpen that calls .claude/setup.mjs. These files create a route for executing the payload from a checked-out repository.

Why This Matters

VS Code blocks automatic tasks in an untrusted workspace and prompts before allowing them by default. Claude Code applies workspace trust to repository-supplied project settings. However, once a developer clicks “Trust” or allows the task, the payload runs.

At 5:40 p.m. IST on August 4, both hook files were still present on the main branch. The core/keyv/package.json manifest still declared version 6.0.0 and listed setup.mjs and Math_Symbol.js for publication. This means anyone who cloned the repository and trusted the workspace could trigger the malware without ever running npm install.

Semgrep documented the same hook pattern, the same setup.mjs filename, and the same Bun 1.3.13 download in an April 2026 compromise of the lightning PyPI package. This overlap strongly suggests the same malware family is now targeting both npm and PyPI.

A modern developer desk with multiple monitors displaying code and an AI coding assistant interface

Why Provenance Signatures Did Not Help

The poisoned Keyv release carried valid OIDC and SLSA provenance. The attestation correctly identified the build process. The packages really were built by the legitimate GitHub Actions runner. The signature was real.

But provenance attests to the build pipeline, not the source code that enters it. The attacker pushed malicious source to the repository, the pipeline built it, and the provenance signature made the result look trustworthy. This is a critical distinction that many automated dependency scanners miss.

The commit that planted the hooks even carried a green GitHub-verified badge and named github-actions[bot] as its author. The verified badge only proves the signature was valid. It does not prove who controlled the credential that submitted the commit.

This incident joins a growing list of attacks where provenance alone failed. The June 2026 compromise of @redhat-cloud-services packages also used OIDC tokens to publish Trojanized packages with valid SLSA provenance. The certificate was accurate, but the source was poisoned.

The Bigger Picture: A Pattern of npm Worms

The Keyv incident is not an isolated event. It fits into a clear pattern of escalating npm supply chain attacks that began with the original Shai-Hulud worm in September 2025.

The Shai-Hulud Family Timeline

In September 2025, the first Shai-Hulud wave compromised over 180 packages. It used phishing to steal maintainer credentials, then deployed secret-scanning tools to find more tokens and published itself into additional packages automatically.

By late 2025, Shai-Hulud 2.0 expanded to nearly 800 packages and hit projects connected to Zapier, ENS Domains, PostHog, and Postman. The 2.0 variant added destructive capabilities, corrupting local files when it found no valid credentials to steal.

In May 2026, the Mini Shai-Hulud campaign compromised TanStack, Mistral AI, UiPath, and over 160 additional packages. Attackers poisoned the GitHub Actions cache, extracted OIDC tokens from runner memory, and published malicious versions with valid provenance.

On May 19, 2026, the @antv wave published 639 malicious versions across 323 packages in a single 22-minute burst. The same day, TeamPCP open-sourced the Mini Shai-Hulud toolchain, making the attack infrastructure available to any competent actor.

What This Trend Means for Developers

Self-propagating worms have become the new baseline for npm threats. Attackers no longer need to manually compromise each package. They steal one set of credentials, the malware spreads itself, and the registry distributes the poison automatically.

The Keyv incident shows this model scaling to over two billion monthly installs. When a worm can jump from one maintainer’s account to dozens of others within hours, namespace-level blocklists become unreliable. Some related packages remained clean while unrelated ones got infected.

Immediate Steps to Protect Your Projects

Check Your Lockfiles

Do not rely on a cached list of “latest” tags. The registry changed too quickly during this incident to support a fixed list. You need to check the exact package names, resolved versions, and lockfiles in your projects.

Known malicious versions include keyv@6.0.0, flat-cache@6.1.24, file-entry-cache@11.1.6, cacheable@2.5.1, cacheable-request@13.0.20, cache-manager@7.2.10, and multiple @cacheable scoped packages. Aikido also confirmed @deliveroo/reevent@1.0.1, @picsart/ai-sdk@3.32.2, @qlik/embed-runtime@1.6.4, and picasso.js@2.11.6.

Disable Lifecycle Scripts

npm 12 blocks unapproved dependency lifecycle scripts by default. If you use an earlier npm client, run installs with the –ignore-scripts flag. Add npm config set ignore-scripts true to your global configuration. This single setting blocks the most common malware execution path.

Some packages need install scripts to compile native code. The safe approach is to disable scripts globally, then allowlist only the specific trusted packages that genuinely require a build step.

Pin Your Dependencies

Use exact versions in your package.json and commit your lockfile. Run npm ci –ignore-scripts in CI pipelines. Avoid permissive version ranges like ^6.0.0 that automatically pull the latest release. The attacker bumped version numbers beyond legitimate releases to exploit these ranges.

How to Clean Up After Exposure

Step 1: Remove Persistence Artifacts First

SafeDep warns that the malware installs a credential-revocation watcher. If you rotate tokens before removing this watcher, you may trigger an attacker-supplied local handler. Check for and remove:

  • .claude/setup.mjs and .vscode/setup.mjs in any cloned repositories
  • Systemd services or LaunchAgents that reference bun-dl or similar patterns
  • Files in /tmp/bun-dl-*/ directories
  • Any suspicious background processes polling GitHub APIs

Step 2: Delete and Reinstall node_modules

Delete your node_modules directory entirely. Reinstall from known-clean package versions that predate August 4, 2026. Use npm install –ignore-scripts during reinstallation. For the Keyv family, SafeDep confirmed that Keyv 5.x and the published @keyv/* adapters remained clean.

Step 3: Rotate All Credentials

Treat any workstation or runner that executed an affected version as credential-exposed. Revoke and regenerate:

  • npm publish tokens and .npmrc credentials
  • GitHub Personal Access Tokens and GitHub Actions secrets
  • AWS access keys, GCP service accounts, and Azure service principals
  • Kubernetes service-account tokens
  • HashiCorp Vault client tokens
  • SSH keys and database connection strings
  • Any secrets stored in password managers on affected machines

Step 4: Audit Your Environments

Review cloud access logs, GitHub repository access logs, and npm publish logs for unauthorized activity. Check for injected branches, unauthorized workflows, or suspicious commits with patterns like “chore: update dependencies.” Monitor for the user-agent Bun/1.3.13 performing unexpected API calls.

Building Long-Term Supply Chain Resilience

Verify, Do Not Trust

Provenance signatures, green verified badges, and high download counts are not safety guarantees. They verify the build pipeline, not the source code. You need to layer additional controls on top of provenance.

Adopt Software Composition Analysis

Run SCA tools on every build. Look for unexpected file additions like setup.mjs, massive size increases in published packages, and new preinstall hooks. The Math_Symbol.js payload added 728 KB to packages that normally ship a few kilobytes of library code. That size jump alone is a reliable detection signal.

Isolate CI/CD Environments

Use short-lived OIDC tokens instead of long-lived secrets. Limit workflow permissions with the principle of least privilege. Separate build runners from production environments. If a runner gets compromised, the blast radius should not include your entire cloud infrastructure.

Monitor for Worm Indicators

Set up alerts for:

  • Unexpected preinstall or postinstall hooks in dependencies
  • Downloads of Bun or other runtimes during npm install
  • Outbound connections to unknown domains during builds
  • New GitHub repositories created from your CI runners
  • Rapid version bumps across multiple packages in the same namespace

Stay Informed

The npm threat landscape changes daily. Follow security researchers at SafeDep, Socket, Aikido, Wiz, and Snyk. Subscribe to npm security advisories. Join communities that track open-source supply chain risks. The attackers share tools and techniques openly; defenders should share intelligence just as freely.

Conclusion

The Keyv npm worm demonstrates how quickly a single compromised account can cascade into an ecosystem-wide crisis. In just hours, attackers turned a trusted caching library into a credential-stealing, self-propagating threat that reached hundreds of packages and billions of monthly installs.

The attack succeeded not because developers were careless, but because the npm trust model assumes maintainers are always honest and provenance signatures always mean safety. Both assumptions failed. The malware exploited lifecycle scripts that run by default, harvested credentials from CI runners, and used valid build signatures to appear legitimate.

Protecting yourself requires a shift in mindset. Disable install scripts by default. Pin exact versions. Audit your lockfiles. Treat provenance as one signal among many, not a guarantee. And if you even suspect exposure, remove persistence artifacts before you rotate credentials.

The Shai-Hulud family is not going away. The May 2026 open-source release of the Mini Shai-Hulud toolchain means any competent actor can replicate these attacks. The Keyv incident is the latest chapter in an ongoing story, not the final one.

Want more hands-on Linux guides like this?

Subscribe to the GEANTECHNOLOGY newsletter for weekly tutorials on networking, cybersecurity, and server administration — or take the next step and secure your infrastructure further.

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *