ChainDrop/Mini Shai-Hulud npm Worm Compromises keyv, cacheable, and 400+ Downstream Packages via Ethereum-Resolved C2 — Threadlinqs Intelligence
As of 2026-09-01, ChainDrop/Mini Shai-Hulud npm Worm Compromises keyv, cacheable, and 400+ Downstream Packages via Ethereum-Resolved C2 is a critical-severity supply chain threat attributed to TeamPCP, tracked by Threadlinqs Intelligence with 9 detection rules (Splunk SPL, Microsoft KQL, Sigma) and 29 indicators of compromise.
Threat ID: TL-2026-2285 · Severity: CRITICAL · Status: ACTIVE · Category: SUPPLY_CHAIN
Attribution: TeamPCP · FINANCIAL
On August 4, 2026, attackers compromised the GitHub account of the keyv/cacheable maintainer and published trojanized releases (keyv@6.0.0 and nine sibling packages) carrying a preinstall-hook dropper
At approximately 09:00 UTC on August 4, 2026, a threat actor compromised the GitHub account of jaredwray, maintainer of the widely-used keyv (600M+ monthly downloads) and cacheable npm namespaces, and pushed malicious commits directly to the keyv repository's main branch. Within minutes the actor published keyv@6.0.0 along with malicious versions of cacheable-request@13.0.20, cache-manager@7.2.10, @cacheable/utils@2.5.1, flat-cache@6.1.24, and at least five other packages in the same namespaces.
Each trojanized release added a `"preinstall": "node setup.mjs"` entry to package.json. setup.mjs is a base64/RC4-obfuscated stager using control-flow flattening that checks for and downloads the Bun JavaScript runtime v1.3.13 directly from Bun's official GitHub releases (not attacker infrastructure) into a /tmp/bun-dl-*/ staging directory, then hands execution to a 727,680-byte compiled Bun CommonJS bundle named Math_Symbol.js (worm-propagation builds use the filename math_init.js). Running the payload under Bun rather than Node.js gives the malware a current, predictable execution environment regardless of the victim's installed Node version and avoids Node-focused EDR heuristics.
The payload's credential-harvesting component ("collector") scans for npm tokens (.npmrc), GitHub personal-access/session/OIDC tokens (including GitHub Actions ACTIONS_ID_TOKEN_REQUEST_TOKEN/URL), AWS IAM role credentials and Secrets Manager/SSM Parameter Store secrets, GCP/Azure/Alibaba/Tencent cloud credentials, HashiCorp Vault tokens, Kubernetes service-account tokens, database connection strings, CI/CD secrets (Jenkins master.key, Argo CD, Harbor), AI-tooling credentials (Anthropic/Claude, OpenAI, Cursor, Gemini), and cryptocurrency wallets (Foundry, Solana, Monero). Stolen tokens are pre-validated in real time against registry.npmjs.org/-/whoami before exfiltration. Harvested data is gzip-compressed, encrypted with a randomly generated AES-256-GCM key, and that key is itself RSA-encrypted under an attacker-controlled public key before exfiltration.
Rather than hardcoding a C2 domain, the malware queries an Ethereum smart contract (StringListStore, address 0xE1f2395ee43e45A1556EC6438a88c31B83493103) via eth_call through legitimate public RPC endpoints (eth-mainnet.nodereal.io, go.getblock.io, eth.llamarpc.com) to retrieve the current exfiltration endpoint at runtime, blending C2 lookups into normal blockchain-developer network traffic. Observed resolved/fallback exfiltration and staging domains include npm-cache.com, pypi-get.com, js-mirror.com, and the DGA-style awqhnjewqjkl.icu. When smart-contract resolution or direct exfiltration fails, the malware falls back to creating public GitHub repositories under compromised identities (546 identified, description "Shai-Hulud: Here We Go Again", containing a results/ directory) as a dead-drop; per one vendor's analysis the only hosts strictly required for this fallback path are github.com, api.github.com, and registry.npmjs.org, since stolen GitHub tokens alone are sufficient to create repositories and exfiltrate via the authenticated-user API.
Self-propagation logic identifies npm accounts/tokens with publish permission and bypass_2fa enabled reachable from harvested credentials, downloads the latest tarballs of every package the compromised identity maintains, injects the same preinstall hook plus setup.mjs/Math_Symbol.js (or setup_bun.js/bun_environment.js in the related Shai-Hulud "Second Coming"/V2 lineage), and republishes trojanized versions signed under the victim's legitimate identity. Because the republished packages pass through real GitHub Actions build pipelines, they carry valid OpenID Connect and SLSA provenance and Sigstore/Rekor-signed attestations with a green GitHub-verified badge (commit author github-actions[bot]) — the build process is faithfully attested, but the attestation cannot establish that the source entering the pipeline was safe, defeating provenance-based trust checks. Sep
Target sectors: softwaredevelopment, technology, financialservices, cloudservices
Target regions: Global
Timeline
- Original Shai-Hulud npm worm compromises 500+ packages via stolen maintainer tokens, using randomized repository names to evade infrastructure-pattern detection; becomes the primary catalyst for npm Trusted Publishing adoption
- Shai-Hulud "Second Coming" / V2 detected: adds setup_bun.js/bun_environment.js Bun-runtime loader, TruffleHog secret scanning, GitHub Actions self-hosted-runner persistence (named SHA1HULUD), and destructive wiper fallback
- TeamPCP-linked supply-chain compromise of Trivy, Checkmarx KICS, and LiteLLM using overlapping infrastructure and staging techniques
- PyTorch Lightning PyPI package compromised using identical setup.mjs dropper and Bun 1.3.13 toolkit later reused in the keyv/cacheable attack
- @antv npm ecosystem compromise tied to TeamPCP using the same toolkit lineage
- Attacker compromises maintainer jaredwray's GitHub account at approximately 09:00 UTC and pushes malicious commits to the keyv repository main branch
- keyv@6.0.0 and nine sibling packages across the keyv/cacheable namespaces published with the setup.mjs preinstall-hook dropper within minutes of the account compromise
- Self-propagation logic republishes trojanized versions across 353+ packages within roughly 30 minutes, rising to 868 packages/1,381 versions by 13:37 CEST and ultimately 1,684 poisoned versions across 420 package names in nine npm organizations
- First indicator-of-compromise disclosures published by responding security vendors (13:45 UTC)
- Ethereum smart-contract-based dynamic C2 domain resolution mechanism documented by researchers (15:00 UTC)
- npm restores clean prior versions (keyv@5.6.0, flat-cache@6.1.23, cache-manager@7.2.9, cacheable-request@13.0.19) as the latest dist-tag; malicious keyv@6.0.0 removed from the registry entirely
- Full payload technical breakdown (obfuscation, credential targets, exfiltration mechanics) published by responding researchers (19:50 UTC)
Detections & IOCs
As of 2026-09-03, this threat has 9 detection rule(s) across Splunk SPL, Microsoft KQL and Sigma, and 29 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, T1588, T1584, T1195, T1078, T1059, T1550, T1027, T1553, T1552, T1528