Independent tracker. Not affiliated with npm, GitHub, or any security vendor. chaindrop.org is a testnet faucet directory and shares its name with the worm by coincidence. Every fact below is sourced and linked.

npm supply chain · active incident

The ChainDrop worm

On 4 August 2026 a self-propagating worm reached 444 npm packages in under four hours, starting from a caching library with 153 million weekly downloads. It steals credentials at install time, then publishes itself onward using the credentials it just stole. Here is how to tell whether it reached you.

First publish
09:35 UTC
Patient zero
keyv@6.0.0
Packages
444
Versions
2,212
Executes on
preinstall

Check a lockfile

Runs in your browser. Nothing is uploaded, stored or logged.

Revoking the token is a trigger. Remove the watcher first.

The payload installs a monitor that fires an attacker payload when the stolen GitHub token is revoked. Clean the host before you rotate, not after, and rotate from a machine that never ran the install.

What to do, in order

  1. Find it

    Search package-lock.json, yarn.lock and pnpm-lock.yaml for the affected versions, including transitive dependencies. Check CI caches and artifact repositories too, not just repos.

  2. Clean the host before rotating

    Remove the payload artifacts and the token watcher first. Rotating while the watcher is live triggers it.

  3. Rotate from a clean machine

    npm tokens, GitHub credentials, cloud keys, SSH keys, Kubernetes secrets, Vault values, and every CI secret that was in scope for the affected job.

  4. Check what you publish

    If you maintain npm packages, audit your own registry versions for releases you did not publish. That is how the worm moved.

  5. Pin and rebuild

    Pin known-good versions, purge npm and yarn caches on affected machines and build hosts, then rebuild from a known-good baseline and confirm the artifacts are absent.

The eleven carriers

These shipped the loader and the full 727,680-byte payload directly. Everything else in the affected set was republished automatically by the worm. All eleven have since been reverted to safe versions, but anything that installed them in the window is still exposed.

PackagePoisoned versionPublishedWeekly downloads
keyv6.0.009:35:00153,717,238
flat-cache6.1.2410:10:55149,868,983
file-entry-cache11.1.610:13:02147,558,494
cacheable-request13.0.2010:11:2433,963,726
@cacheable/utils2.5.110:14:218,713,375
cacheable2.5.110:10:447,877,004
@cacheable/memory2.2.110:11:297,176,667
cache-manager7.2.1010:14:414,281,731
@cacheable/node-cache3.1.210:10:341,555,151
ecto5.0.110:28:011,293
@cacheable/net2.1.110:09:44975

How one patch release became 444

  1. 09:02

    Poisoned commit lands in jaredwray/keyv

    Commit ee2681a, authored as the maintainer but unsigned, injects setup.mjs and Math_Symbol.js, plants a cover test, and rewrites the release tooling so the next version publishes under the latest dist-tag.

  2. 09:04

    Editor and AI-agent hooks planted

    A second commit adds .claude/settings.json (SessionStart hook) and .vscode/tasks.json (runOn: folderOpen), each executing a copy of the dropper. Opening the folder is enough to run it.

  3. 09:35

    keyv@6.0.0 publishes with valid provenance

    The project’s own release workflow publishes through GitHub Actions OIDC trusted publishing, carrying a genuine SLSA attestation. Provenance gates wave it through, because the provenance is real. The release process was subverted, not forged.

  4. 09:38

    The worm starts publishing itself

    Using credentials harvested from the first victims, the payload enumerates every package the stolen token can publish, injects itself, increments the patch version, and republishes. No attacker infrastructure is involved at any hop.

  5. 10:17

    First public alarm

    Issue jaredwray/cacheable#1689, "[URGENT] Repository compromised", already identifies it as a worm.

  6. 13:20

    444 packages, 2,212 versions

    Spread across @servicetitan (141), @onereach (78), @or-sdk (74), @ornikar (42), @qlik (28), @nebula.js (22) and others. npm unpublishes had begun at 10:39; by 18:10 all 11 tier-1 carriers were reverted.

Indicators of compromise

Defanged where they are attacker-controlled. Use these to hunt on developer machines and build runners, not just in lockfiles.

    On disk

  • node_modules/**/setup.mjsdropper; also aliased math_init.js and router_runtime.js
  • node_modules/**/Math_Symbol.jsstage 2, 727,680 bytes
  • $TMPDIR/bun-dl-*dropper staging directory
  • $TMPDIR/tmp.dpkg_<pid>.lockworm state and beacon file
  • .claude/settings.json, .vscode/tasks.jsonpersistence hooks injected into repos

    SHA-256

  • 54dc7ea54a1317cca0e890a2770630cf7fa6c97813e0cb9d2caa93012b350668setup.mjs, npm tarball preinstall loader
  • fd3ca4007b225fdf8de7af4345a19179d5efa8c4bb9205f88cda806e5684b1ebsetup.mjs, .claude and .vscode repository loader
  • 9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bccMath_*.js stage 2

    Network

  • npm-cache[.]comC2 domain observed in this campaign
  • pypi-get[.]comC2 domain
  • js-mirror[.]comC2 domain
  • 0xE1f2395ee43e45A1556EC6438a88c31B83493103Ethereum mainnet contract serving the C2 list (EtherHiding). No fixed domain to sinkhole.

    Compromised npm publisher accounts

  • jaredwray · thiennq · hubsyncdevops · abarreir-ornikar · sitthidet_arv · rooci · picsart-npm-service-owner · onereach.userIf you maintain packages under any of these, audit for versions you did not publish.

Questions people are asking

Am I affected by the ChainDrop npm worm?

You are affected if your dependency tree resolved to one of the 2,212 poisoned versions across 444 packages, directly or transitively, and you ran an install after 4 August 2026 09:35 UTC. Because the payload runs on a preinstall hook, installing was enough. Paste a lockfile into the checker on this page to compare it against the published list.

Which packages were compromised first?

keyv@6.0.0 was the first, published at 09:35 UTC on 4 August 2026 with over 153 million weekly downloads. Ten more full carriers followed from the same maintainer's projects, including flat-cache@6.1.24 and file-entry-cache@11.1.6. The worm then republished itself into 433 further packages using credentials stolen from each new victim.

Why did provenance and SLSA attestation not stop it?

Because the provenance was genuine. The attacker pushed a poisoned commit and tag to the source repository, and the project's own untouched release workflow built and published it through GitHub Actions OIDC trusted publishing. The signature attests that the workflow published the artifact, which is true. It does not attest that the source was clean.

Should I revoke my GitHub token immediately?

Not as the first step. The payload installs a monitor that fires when the stolen token is revoked. Clean the affected host first, then rotate credentials from a machine that never ran the install.

Is chaindrop.org connected to the ChainDrop worm?

No. chaindrop.org is a Web3 testnet faucet directory that has used the name since before this incident. Researchers independently named the worm ChainDrop in August 2026. The names collide; there is no connection. This page exists because people searching the name deserve accurate information rather than a coincidence.

Sources

Nothing on this page is original research. The affected-package list is parsed from the StepSecurity Threat Center snapshot of 4 August 2026, 18:10 UTC; the analysis is drawn from the reports below. Where they disagree, go to the source.

Also on chaindrop.org

This site tracks a different kind of expiry date: which Ethereum and L2 testnets are still alive, which are being retired and when. Sepolia support ends on 30 September 2026 and most tooling still defaults to it.