Generated by Codex with GPT 5.6 Sol XHigh

Techmeme surfaced Bill Toulas’s August 4 BleepingComputer report, “Massive ChainDrop npm supply-chain attack infects hundreds of packages,” about a self-propagating worm moving through widely used JavaScript packages. The incident’s scale is serious, but its mechanics are the more durable story: ChainDrop turned legitimate release pipelines, trusted package metadata, developer tools, and even routine credential rotation into parts of the attack.

The numbers were still changing as researchers mapped the campaign. BleepingComputer reported more than 1,300 affected packages with roughly two billion combined monthly downloads. A later SafeDep technical analysis enumerated 444 distinct package names and 2,234 poisoned versions across twelve organizations. Those totals measure the footprint differently, but both show why a raw download count should not be mistaken for a count of breached machines. The practical question is whether a poisoned version executed on a developer workstation or CI runner and, if so, which credentials it could reach.

A worm that turns credentials into distribution

The attack first became visible in keyv, cacheable, flat-cache, and file-entry-cache, a family of caching utilities maintained from the same GitHub account. Some are pulled into projects transitively through tools such as ESLint, so teams could be exposed without having selected them directly. The campaign then spread into package namespaces associated with organizations including Deliveroo, Ornikar, OneReach, Picsart, Qlik, and ServiceTitan.

Each poisoned release added a preinstall hook that ran node setup.mjs during an ordinary package installation. The loader fetched the legitimate Bun JavaScript runtime from GitHub and used it to execute an obfuscated payload. That choice reduced the need for conspicuous attacker-hosted infrastructure: a trusted runtime arrived from an official source, performed the malicious work, and was then removed from the temporary directory.

The payload searched broadly for useful authority. BleepingComputer’s list includes GitHub and npm tokens, cloud credentials for AWS, Azure, and Google Cloud, Kubernetes and Vault secrets, database connection strings, private keys, and secrets exposed to GitHub Actions runners. It validated npm tokens against the real registry, then used working credentials to publish poisoned versions of more packages. SafeDep observed some compromised namespaces being republished at roughly one package per second. The package ecosystem supplied both the target list and the distribution network.

Exfiltration also blended into normal development traffic. Rather than depend on an obvious command-and-control domain, the malware encrypted stolen material and placed it in public GitHub “dead-drop” repositories and Actions artifacts. A network policy that merely blocks unfamiliar domains would therefore miss important parts of the chain.

Valid provenance, poisoned source

One of ChainDrop’s sharpest lessons is that authentic provenance is not the same as benign content. In the keyv case, the attacker pushed malicious files into the real source repository and invoked the legitimate GitHub Actions release workflow. The resulting npm package carried valid OIDC identity and SLSA provenance because the official pipeline really had built and published it.

That metadata was not false. It answered a narrower question than many users assume: which workflow produced this artifact from which source revision? It did not establish that the revision was safe or that the account controlling it had not been compromised. SafeDep found the same payload distributed through both an attested pipeline and ordinary stolen npm tokens during the same campaign, demonstrating that defenders have to inspect content and behavior as well as publisher identity.

The source history supplied another misleading signal. SafeDep found a verified GitHub commit attributed to github-actions[bot] with a routine-looking configuration message and a Co-authored-by: claude trailer. GitHub’s badge verified the platform signature on the API-created commit; it did not verify that the displayed author or the change’s intent was trustworthy. Signatures and attestations remain valuable, but ChainDrop shows why they cannot carry the entire trust decision.

Opening the repository could be enough

The compromised keyv repository contained a second execution path aimed at developers who never installed the package. A .vscode/tasks.json task was configured to run when the folder opened, while a .claude/settings.json hook ran at the start of a Claude Code session. Both paths converged on the same payload used by the npm release.

This widened the blast radius from dependency consumers to maintainers, investigators, and coding-agent users. Cloning the repository alone did not execute the malware, according to SafeDep, but opening it in a configured IDE or starting an agent session inside it could. The trap exploited a natural incident-response instinct: pull the suspicious repository locally and inspect it with the tools normally used for software work.

The attack also installed a watcher that monitored whether a stolen GitHub token still worked and executed an attacker-supplied handler when the token was revoked. That dead-man’s switch made standard first-response advice dangerous if performed in the wrong order. SafeDep therefore advised teams to hunt for and remove the watcher before rotating credentials, then rotate every secret reachable from an affected machine or runner.

The engineering takeaway

ChainDrop compresses several software-supply-chain failures into one incident. Package installation scripts provided automatic code execution. Long-lived credentials let one compromised environment reach the next publisher. Legitimate CI and provenance made poisoned releases look formally authentic. Project-local IDE and agent configuration turned source inspection into another execution surface. Credential revocation itself became a trigger.

The response has to be layered as well. Teams should audit lockfiles and caches rather than relying on the registry’s current state, because removed versions can remain on disk or pinned in a build. A workstation or runner that executed an affected release should be treated as compromised, rebuilt from a known-good state, and stripped of persistence before secrets are rotated. CI jobs should receive narrowly scoped, short-lived credentials; lifecycle scripts should be disabled by default or explicitly allowlisted; new package versions should pass an observation period and behavioral review before promotion; and suspicious repositories should be inspected in disposable environments without ambient credentials.

The most important point is not that npm suffered another bad-package incident. It is that modern software authenticity is compositional. A real repository, a verified commit, a legitimate workflow, a valid attestation, and a familiar runtime can all participate in a malicious release when the authority joining them has been stolen. ChainDrop succeeded by making each trusted component perform its normal function on hostile input.