ChainDrop Shai-Hulud npm Attack: Keyv, Cacheable and Hundreds of Packages Compromised


A new wave of the Shai-Hulud software-supply-chain campaign compromised the maintainer behind widely used npm packages including Keyv and Cacheable, then spread into hundreds of additional packages by stealing credentials and abusing legitimate publishing access.

Security firm Aikido says the campaign began on August 4, 2026, when attackers compromised the GitHub account of the maintainer behind keyv. The attackers pushed malicious files directly to project branches and cut new npm releases through legitimate GitHub Actions workflows, so poisoned packages could still carry valid provenance.

The campaign’s package count changed quickly as researchers tracked new propagation. Contemporary reports citing Aikido’s evolving August 5 tally ranged from 444 to 868 unique packages, while 1,381 referred to compromised package versions. Those packages collectively represented more than 2 billion monthly downloads in the researchers’ estimates. Because the campaign was still moving, teams should use a current affected-version feed rather than treating any single headline count as exhaustive.

The practical response is more important than the headline number: if an affected package version executed on a developer workstation or CI/CD runner, removing or downgrading the package is not enough. Treat the environment and its reachable credentials as potentially compromised.

Confirmed affected packages include major caching utilities

Aikido’s initial investigation identified malicious releases across a family of heavily used JavaScript caching packages:

PackageMalicious version reported by AikidoApprox. monthly installs reported by Aikido
keyv6.0.0604M
flat-cache6.1.24580M
file-entry-cache11.1.6571M
cacheable-request13.0.20137M
cacheable2.5.130M
@cacheable/memory2.2.128M
cache-manager7.2.1016M
@cacheable/node-cache3.1.26M

Aikido also observed spread into packages associated with other maintainers and organizations, including Deliveroo, Ornikar, Picsart and Qlik.

Because the worm steals credentials and republishes packages it gains rights to, the affected-package list is not static. Teams should rely on current security advisories, registry metadata and live malware feeds rather than assuming that only the first disclosed packages are relevant.

How ChainDrop executes

The malicious package versions added a preinstall hook:

"preinstall": "node setup.mjs"

That matters because a preinstall hook runs as part of dependency installation, before an application ever imports the affected package.

Aikido says setup.mjs acts as an obfuscated dropper. It downloads the Bun JavaScript runtime and uses Bun to execute a much larger payload called Math_Symbol.js.

The payload is not limited to one credential type. It is designed to inspect developer machines, CI environments and cloud-access material, then encrypt and exfiltrate what it finds.

What the malware tries to steal

Aikido’s analysis shows the payload targeting several high-value credential classes.

npm publishing tokens

The malware reads ~/.npmrc and searches for additional .npmrc files, extracting npm authentication tokens. It can validate tokens against npm before using them.

This is central to the worm’s propagation model: a stolen npm token may grant publishing rights to other packages maintained by the same developer or organization.

GitHub credentials and CI identities

The payload looks for GitHub personal access tokens, OAuth tokens, GitHub App server-to-server tokens and OIDC-related material.

On GitHub Actions runners, Aikido says the malware attempts to read runner-process memory to recover secrets and OIDC tokens used by publishing workflows.

That means a compromise can extend beyond source code and into the identities used to publish otherwise trusted artifacts.

AWS credentials and cloud metadata

The malware targets standard AWS credential files and environment variables, EC2 instance metadata, ECS container metadata and AWS Secrets Manager.

If a compromised CI runner has broad cloud permissions, the blast radius can therefore be much larger than npm itself.

Kubernetes secrets

Aikido says the payload reads Kubernetes service-account credentials and attempts to use them against the Kubernetes API. It also searches common kubeconfig locations.

Vault, SSH, Terraform and other developer secrets

The filesystem scanner targets files including .env files, private keys, SSH credentials, Terraform state and variable files, Docker credentials, KeePass databases, VPN configurations and IDE configuration files.

Aikido also observed checks for Stripe keys and Slack tokens.

The worm can spread through npm and GitHub

ChainDrop is dangerous because credential theft is only one part of its behavior.

npm propagation

When the malware obtains a usable npm token, Aikido says it enumerates packages the token can publish, downloads their current tarballs, injects the malicious preinstall files, increments versions and republishes them.

That turns a single maintainer compromise into a supply-chain multiplier: every newly poisoned package can infect additional developer or CI environments, generating more credentials that can be used to continue propagation.

GitHub repository propagation

The malware also abuses GitHub credentials. Aikido observed it modifying reachable repositories and adding malicious execution hooks to files such as:

  • .claude/settings.json
  • .vscode/tasks.json

Those hooks can trigger when a developer opens a repository in VS Code or starts Claude Code inside it, meaning execution is no longer limited to an npm install event.

Aikido says these commits may appear under the author name claude with the commit message chore: update config, an attempt to make malicious changes blend into ordinary developer activity.

Valid provenance did not mean the package was safe

One of the more important lessons from this incident is that artifact provenance is not the same thing as artifact safety.

Aikido says the attackers committed malicious files directly into legitimate repositories and then released the packages using existing GitHub Actions workflows. The resulting npm releases could therefore be signed by the legitimate build pipeline and carry valid provenance.

Provenance can answer questions such as where an artifact was built and which workflow produced it. It cannot prove that the source code entering that trusted workflow was benign.

This is exactly the failure mode supply-chain teams need to design for: a trusted pipeline can faithfully build and sign malicious source if the repository or maintainer identity has already been compromised.

Why npm v12’s security defaults help — but do not solve this incident class

GitHub has already been hardening npm in response to earlier supply-chain campaigns.

With npm v12, dependency lifecycle scripts such as preinstall, install and postinstall are disabled by default unless explicitly approved. That is directly relevant to malware that relies on automatic preinstall execution.

GitHub has also introduced publish-time malware scanning, and npm trusted publishing can use OIDC instead of long-lived publish tokens. Staged publishing is separately available for workflows that require human approval before a package becomes installable.

These changes raise the attacker’s cost, but they do not remove the need to secure maintainer accounts, GitHub repositories and CI identities. ChainDrop demonstrates why: an attacker who compromises trusted source repositories or developer identities can still abuse legitimate build and publication paths.

What developers and security teams should do now

If you installed or built with an affected version, treat incident response as a host-and-credential compromise problem rather than merely a dependency rollback.

1. Identify exposure

Check lockfiles, CI logs, dependency caches and artifact histories for affected package versions. Do not rely only on the currently installed package tree; a poisoned package may have executed earlier and then disappeared after a later update.

Pay particular attention to developer workstations and CI runners that performed installs while the malicious versions were available.

2. Isolate affected environments

If a poisoned package executed, isolate the workstation or CI runner from sensitive environments until you understand what credentials were reachable.

Ephemeral CI runners should be destroyed and recreated from a trusted image rather than reused.

3. Check for Shai-Hulud persistence before revoking credentials

This ordering matters. Recent Shai-Hulud variants have installed a gh-token-monitor persistence mechanism on Linux and macOS that watches a stolen GitHub token and can trigger a destructive handler when the token is revoked.

Before rotating GitHub or npm credentials from an affected environment, check for indicators including:

  • ~/.local/bin/gh-token-monitor.sh
  • ~/.config/gh-token-monitor/
  • ~/.config/systemd/user/gh-token-monitor.service
  • ~/Library/LaunchAgents/com.user.gh-token-monitor.plist

If these or equivalent persistence artifacts are present, disable and remove the persistence and terminate the running process first. Perform credential rotation from a separate, known-clean system. Do not execute untrusted cleanup scripts from the compromised host.

4. Rotate npm and GitHub credentials from a clean system

After persistence has been addressed, rotate npm tokens, GitHub PATs, OAuth credentials and any affected GitHub App credentials. Review repository access and publishing rights for unexpected changes.

For automated npm publishing, move away from broad long-lived tokens where possible and use tightly scoped trusted publishing/OIDC workflows.

5. Rotate reachable cloud and infrastructure secrets

If the environment held AWS credentials, Kubernetes service-account tokens, Vault tokens, SSH keys, Terraform secrets or other machine credentials, assume they may have been collected.

Credential rotation should be based on what the compromised host could access, not only on what you know was exfiltrated.

6. Audit repositories for malicious persistence

Search for unexpected modifications to .claude/settings.json, .vscode/tasks.json, workflow files and package scripts.

Review suspicious commits around the exposure window, especially automated-looking commits or commits that add execution hooks.

7. Rebuild from known-good state

After persistence is removed and credentials are rotated, rebuild affected developer or CI environments from trusted images. Simply deleting the malicious npm package leaves behind any credentials already stolen and may leave persistence mechanisms untouched.

Indicators published during the investigation

Aikido published the following indicators in its August analysis:

IndicatorValue
Malicious droppersetup.mjs
Main payloadMath_Symbol.js / math_init.js
Dropper SHA-25654dc7ea54a1317cca0e890a2770630cf7fa6c97813e0cb9d2caa93012b350668
Community-spread dropper SHA-256fd3ca4007b225fdf8de7af4345a19179d5efa8c4bb9205f88cda806e5684b1eb
Payload SHA-2569fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc
Fallback endpointnpm-cache[.]com:443/router
GitHub exfiltration markerRepository description containing Shai-Hulud: Here We Go Again

Static indicators are useful for triage, but they should not be treated as sufficient evidence of safety. A self-propagating campaign can evolve quickly, and stolen credentials may be abused long after the original malicious file is gone.

Sources

Comments

Sign in to join the discussion!

Your comments help others in the community.