ChainDrop: Massive npm Supply-Chain Infostealer Worm Compromises 1,300+ Packages via Keyv Maintainer Account Hijack — Threadlinqs Intelligence
As of 2026-08-09, ChainDrop: Massive npm Supply-Chain Infostealer Worm Compromises 1,300+ Packages via Keyv Maintainer Account Hijack is a critical-severity supply chain threat attributed to Shai-Hulud Campaign, tracked by Threadlinqs Intelligence with 9 detection rules (Splunk SPL, Microsoft KQL, Sigma) and 43 indicators of compromise.
Threat ID: TL-2026-1872 · Severity: CRITICAL · Status: ACTIVE · Category: SUPPLY_CHAIN
Updated: 2026-08-09 · revalidated 1× · latest source
Attribution: Shai-Hulud Campaign · ESPIONAGE
A self-propagating infostealer worm dubbed ChainDrop — based on the Shai-Hulud malware framework — has compromised over 1,300 npm packages (1,381 versions) by hijacking the GitHub account of the
On August 4, 2026 at approximately 09:02 UTC, an unidentified threat actor compromised the GitHub account of Jared Wray, the maintainer of the Keyv caching library (~153.7M weekly downloads) and the broader cacheable ecosystem. Over the next ~4 hours, the attacker pushed poisoned commits directly to main branches across multiple repositories, bypassing branch protection via the compromised account's credentials. The first malicious package published was keyv@6.0.0, which carried a preinstall script (setup.mjs) and an obfuscated 728 KB payload (Math_Symbol.js). Crucially, because the attacker pushed the poisoned release commit through the maintainer's own GitHub Actions workflows, npm's OIDC trusted publishing system and SLSA provenance attestation both registered as fully valid — the attestation faithfully recorded the poisoned commit hash. This demonstrates a critical gap: provenance proves which commit was built but cannot prove the commit was authorized.
The dropper (setup.mjs) is a cross-platform runtime downloader that fetches the legitimate Bun v1.3.13 runtime from the official oven-sh/bun GitHub releases — a living-off-the-land approach. It detects the platform and architecture (Linux x64 glibc/musl, Linux arm64, macOS x64/arm64, Windows x64/arm64), downloads the appropriate Bun artifact, stages it in /tmp/bun-dl-*, and executes Math_Symbol.js via Bun. After execution, it deletes the staging directory. A second variant of setup.mjs (11,017 bytes, SHA-256 fd3ca400) appeared in community-propagated packages, featuring a hand-rolled minimal ZIP extractor as fallback.
The Stage 2 payload Math_Symbol.js (or math_init.js, identical SHA-1 35a672cf) is a Bun-bundled CJS program weighing 727,680 bytes with three layers of obfuscation: a rotated 1,283-entry string table with custom charset decoder, anti-tamper Object.hardening, and AES-256-GCM encrypted configuration blobs. On execution, it reads GITHUB_REF and GITHUB_REPOSITORY for encrypted target matching on special-cased repos, checks for a Russian locale kill switch (LANG set to Russian causes the payload to exit with 'Exiting as russian language detected!'), detaches and self-respawns outside GitHub Actions via spawn(process.execPath) with _NODE_RUNTIME_INIT to survive the parent npm install process, and writes a camouflage lock file at /tmp/tmp.dpkg_<pid>.lock disguised as a dpkg lock.
The payload performs the most extensive credential harvesting observed in a supply-chain worm, targeting: GitHub tokens (PATs ghp_, OAuth gho_, runner ghs_ and JWT OIDC tokens), npm tokens (npm_ format validated against registry.npmjs.org/-/whoami), AWS credentials (env, ~/.aws/credentials, IMDSv2, ECS metadata, Secrets Manager via ListSecrets + GetSecretValue across 16 regions, SSM GetParameters with decryption), GCP credentials (~/.config/gcloud, service account JSON), Azure credentials (~/.azure/accessTokens.json), Kubernetes secrets (in-cluster API enumeration across all namespaces), HashiCorp Vault (token from env or file, Kubernetes auth, AWS IAM auth, mount enumeration + KV v1/v2 path walk), and over 140 filesystem hotspot paths including .npmrc, .git-credentials, SSH keys, Docker config, .env files, shell histories, password-store entries, and AI-agent credential stores (Claude, Codex, Cursor, OpenAI, Anthropic, Gemini, OpenClaw, OpenCode, Hermes, Kiro). Notably, the payload includes a sudo python3 helper that reads the GitHub Actions Runner.Worker process memory via /proc/*/mem to extract all secrets with 'isSecret':true in-scope from active workflow runs.
Self-propagation is the worm's defining feature. Using stolen npm tokens, the worm lists all publishable packages for the victim account via npm API queries, downloads each current tarball, bumps the patch version, injects setup.mjs + math_init.js, adds the preinstall hook, and republishes with self-generated Sigstore + SLSA provenance bundles. Using stolen GitHub ghs_ tokens, it pushes malicious .claude/settings.json and .vsc
Target sectors: technology, softwaredevelopment, cloudcomputing, finance
Target regions: Global
Detections & IOCs
As of 2026-08-15, this threat has 9 detection rule(s) across Splunk SPL, Microsoft KQL and Sigma, and 43 indicator(s) of compromise. Detection query text and full IOC values are available to authenticated users and programmatically via the Threadlinqs MCP server (Purple tier). View plans.
SUPPLY_CHAIN, CRITICAL, threat intelligence, cybersecurity, T1195, T1195.002, T1195.001, T1204.002, T1059.007, T1059.006, T1202, T1543.001, T1053.005, T1601