On August 4, 2026, a self-propagating worm tore through the npm ecosystem in under four hours, infecting 444 packages and 2,212 versions with payloads cryptographically attested as legitimate. ChainDrop exploited no vulnerability in the registry or signing protocols; it used OIDC Trusted Publishing and SLSA attestations exactly as any legitimate publisher does. The only difference was control of the compromised account.
The attack proves that automated provenance, on its own, no longer distinguishes safe software from malicious. When the entry point is a high-profile maintainer with a trusted workflow, the signature becomes a veil rather than a filter.
- The ChainDrop worm infected 444 npm packages and 2,212 versions between 09:40 and 13:20 UTC on August 4, 2026, according to StepSecurity; the count was still climbing at 18:10 UTC.
- The initial packages carried valid SLSA attestations published via OIDC Trusted Publishing, making them indistinguishable from legitimate releases to any automated verification.
- The ~710 KB payload uses the legitimate Bun runtime as an execution vehicle, steals CI/CD and developer credentials from the filesystem, environment variables, and process memory, then self-propagates on npm.
- Command-and-control infrastructure rests on an Ethereum smart contract that dynamically updates C2 domains; Unit 42 observed a full reconfiguration via a single transaction late on August 4.
How the Infection Started: An Account, Not a Vulnerability
The trigger occurred at 09:02:37 UTC with poisoned commits pushed from the GitHub account of Jared Wray, maintainer of high-traffic packages in the npm ecosystem. Available sources do not confirm the initial access vector: phishing, credential stuffing, or another mechanism remain unconfirmed. Wray subsequently stated, per CSO Online, that he used OIDC and one-time codes, not long-lived static tokens, and regained control of the account at 20:00 UTC.
From that initial access, carrier packages were published through automated Trusted Publishing workflows. StepSecurity notes that the 11 tier-1 packages — including keyv@6.0.0, flat-cache@6.1.24, and file-entry-cache@11.1.6 — accounted for over 450 million combined weekly downloads. Flat-cache alone recorded 150,868,983. These packages are transitive dependencies of ubiquitous tools like ESLint; their installation often occurs without direct scrutiny by end developers.
The Dropper Mechanism: Bun as a Vehicle, Not a Target
Compromised packages execute a preinstall hook that launches setup.mjs. This script checks for the Bun runtime in PATH; if absent, it downloads it from the official GitHub repository of Oven, the company that develops it. Palo Alto Networks Unit 42 clarifies: "To be clear: Bun is not compromised. The attacker is using a legitimate runtime as a portable execution vehicle." The legitimate runtime thus becomes the portable container for the subsequent payload.
The second-stage payload — Math_Symbol.js, also known as math_init.js — is a 727,680-byte obfuscated JavaScript file compressed into two lines. Its size (~710 KB) makes it theoretically detectable, but its delivery through a known runtime and execution within the dependency-installation context reduce operational visibility.
The worm adapts its behavior to the environment. On developer workstations it detaches into the background; in CI runners it stays inline in the job to capture workflow secrets. Unit 42 reports that "if it detects a CI environment it runs inline in the job instead, which means its own debug output lands in the workflow log" — a detail that enabled retrospective observation but did not prevent initial execution.
Credential Theft: From Runner Memory to npm Tokens
The payload implements a particularly aggressive memory-scraping mechanism. An embedded Python helper in the encrypted blob locates the Runner.Worker process on GitHub Actions, opens /proc/<pid>/maps and /proc/<pid>/mem, extracting ephemeral OIDC tokens and other runner secrets. Unit 42 emphasizes: "Rather than waiting for a file to be written to disk, the worm searches memory. In the process, it captures secrets that may have been designed to vanish when a job finishes." OIDC tokens are designed for short expiry; memory access makes them vulnerable before natural deletion.
Stolen credentials — from filesystem, environment variables, and process memory — enable authentication to npm, GitHub, AWS, Kubernetes, and HashiCorp Vault. The worm verifies package-write permissions and 2FA bypass, then downloads tarballs, injects the malware, increments the patch version, and republishes. Microsoft Threat Intelligence describes this routine: "payload's package-propagation routine downloads each publisher's latest release, inserts itself, increments the patch version, and publishes the resulting archive." The 433 tier-2 packages were generated automatically via this mechanism, in addition to the 11 initial carriers.
Cross-Linked Persistence: When VS Code and Claude Code Become Vectors
ChainDrop does not stop at the npm installation pipeline. Unit 42's deobfuscated analysis shows cross-linked persistence across development environments: the file .vscode/tasks.json contains an "Environment Setup" task with runOn: folderOpen that executes node .claude/setup.mjs; conversely, .claude/settings.json sets a SessionStart hook that executes node .vscode/setup.mjs. Unit 42 defines this mechanism as "cross-referencing is a naming trick that makes each artifact look like it belongs to the other tool."
This architecture expands the attack surface beyond the traditional IDE, touching AI assistants integrated into developer workflows. Microsoft Threat Intelligence specifically analyzed the "Mini Shai-Hulud" component and its persistence in Claude Code. The infection thus becomes a developer-to-developer path, independent of the original npm installation.
Unit 42 also flags decrypted routines for persistent token monitors on macOS (LaunchAgent) and Linux (systemd service), but notes that in the analyzed sample these routines were not invoked. Their activation status in real environments remains unverified by available sources.
C2 on Blockchain: The Impossibility of Traditional Takedown
Command-and-control infrastructure rests on an Ethereum smart contract at address 0xE1f2395ee43e45A1556EC6438a88c31B83493103, with selector 0x53ed5143. The malware dynamically resolves the C2 endpoint by querying the blockchain; the active domain is npm-cache[.]com. Late on August 4, 2026, Unit 42 observed the adversary "silently reconfiguring the worm's entire C2 infrastructure through a single Ethereum transaction, without requiring any update to the deployed malware." Fallback operates on public GitHub repositories with the description "Shai-Hulud: Here We Go Again," identified by Unit 42 in 453 repositories — removed at the time of analysis publication.
The use of Ethereum for C2 renders takedown based on abuse reporting to DNS registrars or hosting providers ineffective: the blockchain has no central authority that can block or modify a smart contract. Data exfiltration itself uses AES-256-GCM encryption with a random key, then encrypted with the attacker's public key via RSA-OAEP-SHA256.
"Provenance proves which commit was built. It cannot prove the commit was authorized." — StepSecurity
What to Do Now
Microsoft Threat Intelligence states: "Organizations that installed an affected package with lifecycle scripts enabled should treat the associated developer workstation or build runner as potentially compromised." Available sources indicate the following priority actions:
- Treat any developer workstation or CI/CD runner that installed affected versions during the 09:40–13:20 UTC window on August 4, 2026, as potentially compromised, with full credential rotation.
- Check for .vscode/tasks.json and .claude/settings.json files with cross-references to setup.mjs, an indicator of the cross-linked persistence documented by Unit 42.
- Monitor for the creation of public GitHub repositories with the description "Shai-Hulud: Here We Go Again," the exfiltration fallback pattern identified by Microsoft Threat Intelligence.
- Require rebuilds from trusted sources with manual source-code verification, given that automated SLSA attestations did not prevent payload distribution.
The Lesson: Provenance Is Genealogy, Not a Guarantee
StepSecurity frames the problem with synthetic precision: provenance attests which commit an artifact derives from, not that the commit was legitimate. ChainDrop exploits this operational distinction: the cryptographic mechanisms function correctly, but the trust anchor — the maintainer's account — is yielding. The assumption that valid provenance equals security has proven to be a single conceptual point of failure.
The sector impact exceeds the specific incident. Automated provenance checks, increasingly adopted as compliance requirements, do not detect compromised accounts with legitimate workflows. The use of blockchain for C2 adds a dimension of legal untouchability. Persistence in AI coding assistants expands the perimeter beyond the traditional. The combination of these elements defines a new standard of sophistication for software supply-chain attacks.
The worm was active and propagating at the time of analysis publications. No source indicates complete eradication.
Why did the malicious packages have valid SLSA attestations?
SLSA attestations verify that an artifact derives from a specific commit via a trusted workflow. Because the attacker controlled the maintainer's GitHub account, they could execute legitimate OIDC Trusted Publishing workflows, generating cryptographically correct attestations for poisoned commits. The signature is valid; the intent is fraudulent.
Was the Bun runtime compromised?
No. Bun is a legitimate runtime developed by Oven. The attacker downloads it from the official repository and uses it as a portable execution vehicle for the obfuscated payload. The runtime itself contains no malicious code; it is the tool, not the target.
What is the significance of the Russian-language check in the payload?
The payload contains a routine that silently exits on systems with a Russian locale, printing "Exiting as russian language detected!". This pattern is documented by technical sources, but the motive — deterrence, avoiding specific targets, or other — is unconfirmed in the available dossier.
Sources
- https://www.stepsecurity.io/blog/chaindrop-npm-worm
- https://unit42.paloaltonetworks.com/chaindrop-npm-worm-analysis/
- https://www.microsoft.com/en-us/security/blog/2026/08/04/chaindrop-supply-chain-compromise-anatomy-self-propagating-worm/
- https://www.csoonline.com/article/4205276/chaindrop-credential-stealing-worm-infects-over-400-npm-packages.html
- https://www.stepsecurity.io/start-free
- https://app.stepsecurity.io/github/actions-security-demo/comp-packages/actions/runs/30903869229?tab=process-events&jobId=91974344803
- https://docs.stepsecurity.io/workspace/threat-center
Information verified against cited sources and current as of publication.