Threat reportSupply ChainTL-2026-1875
ChainDrop npm Supply-Chain Compromise: Self-Propagating Mini Shai-Hulud Credential-Stealing Worm Affecting 444+ Packages
ChainDrop npm Supply-Chain Compromise (TL-2026-1875), also tracked as ChainDrop, is a critical-severity supply-chain compromise, first published 2026-08-04 and last reviewed 2026-10-05. It is attributed to TeamPCP with medium confidence, affects jaredwray / npm keyv, maps to 46 MITRE ATT&CK techniques (T1003, T1005, T1008), and is covered by 9 detection rules and 45 indicators of compromise.
- Severity
- CRITICALAssessed severity
- CVEs
- 0None referenced
- Techniques
- 46MITRE ATT&CK
- Actors
- 1TeamPCP
- Detection rules
- 9SPL · KQL · Sigma
- IOCs
- 45Indicators of compromise
Key facts for TL-2026-1875
- Threat ID
- TL-2026-1875
- Also known as
- ChainDrop, Mini Shai-Hulud worm, Shai-Hulud 3.0, Keyv supply-chain compromise
- Severity
- CRITICAL
- Status
- ACTIVE
- Category
- SUPPLY_CHAIN
- First published
- Last reviewed
- Attribution
- TeamPCP
- Attribution confidence
- MEDIUM
- Motivation
- FINANCIAL
- Target sectors
- softwaredevelopment, technology, cloudcomputing, cybersecurity, devops, ecommerce, health, financialservices
- Target regions
- Global
- Detection rules
- 9
- Indicators of compromise
- 45
- Updates
- 2026-10-05 · 4 updates · revalidated 4× · latest source
How ChainDrop npm Supply-Chain Compromise works
ChainDrop is a large-scale npm supply-chain attack affecting 444+ packages (2,212 malicious versions) across 14+ unrelated publisher organizations, delivered via a Mini Shai-Hulud self-propagating credential-stealing worm. Malicious releases execute via the npm preinstall lifecycle hook, steal credentials (npm, GitHub, AWS, Azure, GCP, Kubernetes, HashiCorp Vault, AI agent configs, cryptocurrency wallets), exfiltrate via Ethereum blockchain-resolved C2 with AES-256-GCM + RSA-OAEP encryption, and republish modified packages to propagate, including via GitHub Actions OIDC abuse for trusted-publisher publication carrying valid SLSA provenance.
On August 4, 2026 (UTC), the npm ecosystem experienced one of the most sophisticated supply-chain attacks ever recorded. Dubbed ChainDrop, the attack propagated via a Mini Shai-Hulud variant worm that poisoned 444 packages (2,212 versions) in under four hours, affecting packages with a combined 2+ billion monthly installs. The attack began with the compromise of the GitHub account of Jared Wray, maintainer of the Keyv package (153.7M weekly downloads), and rapidly spread across the jaredwray ecosystem to packages including flat-cache (149.9M), file-entry-cache (147.6M), cacheable-request, cache-manager, ecto, and then autonomously propagated to 433 additional packages across 14+ organizations including ServiceTitan, OneReach, Ornikar, Qlik, Picsart, and Deliveroo.
The initial compromise was achieved via stolen GitHub maintainer credentials, not an npm token — the attacker pushed unsigned commits directly to the main branch and triggered legitimate release workflows configured with OIDC trusted publishing. This meant that every malicious version from the jaredwray wave carried valid SLSA provenance attestation signed by GitHub Actions. The resulting provenance accurately recorded the poisoned commit hash; it could not prove the commit was authorized.
The worm delivery mechanism exploits npm's preinstall lifecycle hook. Each poisoned package includes a setup.mjs file (29,918 bytes, wave 1; 11,017 bytes, re-obfuscated wave 2) and a heavily obfuscated 727,680-byte Bun-bundled second-stage payload (Math_Symbol.js or math_init.js). When npm install runs, the preinstall hook executes setup.mjs via Node.js, which downloads the legitimate Bun v1.3.13 JavaScript runtime from the official oven-sh/bun GitHub release and uses it to detonate the second-stage worm. The worm downloads a platform-specific Bun binary (Linux x64 glibc/musl, Linux arm64, macOS x64/arm64, Windows x64/arm64) and cleans up the staging directory afterward. If Bun is already installed, the download is skipped. The second-wave dropper variant includes a hand-rolled minimal ZIP extractor with PowerShell Expand-Archive fallback on Windows.
The stage 2 payload (727,680 bytes) is a Bun-bundled CommonJS program with three obfuscation layers: a rotated 1,283-entry string table with custom charset decoder, anti-tamper Object hardening, and AES-256-GCM encrypted configuration blobs. Its startup sequence includes a Russian-locale kill switch (exits if LANG indicates a Russian locale — a classic CIS avoidance pattern), a detached self-respawn mechanism outside GitHub Actions, and anti-debug checks. It writes a camouflaged state file at $TMPDIR/tmp.dpkg_<pid>.lock disguised as a dpkg lock.
The credential harvesting subsystem targets approximately 140 filesystem paths across 19 categories. These include npm tokens (~/.npmrc, ~/.yarnrc), GitHub tokens (via gh auth token and filesystem scanning), AWS credentials (~/.aws/credentials, config, IMDSv2, ECS metadata), Azure tokens (az account get-access-token, ~/.azure/accessTokens.json), Google Cloud (~/.config/gcloud, gcloud config config-helper), Docker (~/.docker/config.json), Kubernetes (~/.kube/config, in-cluster API enumeration), SSH keys (~/.ssh/), HashiCorp Vault (token discovery, Kubernetes auth, AWS IAM auth, KV v1/v2 path walk across all mounts), Jenkins (master.key), Terraform state files, PostgreSQL and MySQL connection strings, and cryptocurrency wallet.dat files (Bitcoin, Dash, Dogecoin, Litecoin, Zcash, Electrum). The worm also performs AWS Secrets Manager ListSecrets/GetSecretValue and SSM GetParameters calls across 16 regions, and Kubernetes namespace-wide secret enumeration.
A distinctive new capability in this generation targets AI developer tools — credential stores for Claude Code (.claude/credentials.json, .claude.json), OpenAI (.openai/auth.json), Codex (.codex/auth.json), Cursor (.cursor/credentials.json), Anthropic (.anthropic/auth.json), Gemini (.gemini/.env), OpenClaw, OpenCode, Hermes, and Kiro. The worm also performs GitHub Actions Runner.Worker memory scraping via sudo python3 — dumping readable pages of /proc/<Runner.Worker PID>/mem and grepping for "isSecret":true JSON fragments to extract every secret injected into CI/CD workflows.
The worm scans discovered credentials via 19 secret format regexes covering GitHub PATs (ghp_, gho_, ghs_, JWT formats), npm tokens (npm_), AWS key/secret/session formats, GCP service account JSON, Azure keys, database connection strings, Stripe, Slack, Twilio, SSH private keys, Docker auth configs, kubeconfigs, and generic password/token key-value pairs. Each credential is validated against the service API in real-time.
C2 infrastructure employs a defensive-resilient multi-layer architecture. The primary C2 resolution uses an Ethereum smart contract at 0xE1f2395ee43e45A1556EC6438a88c31B83493103 (function selector 0x53ed5143) via eth_call, querying 75 public RPC endpoints in order to retrieve the current C2 domain list — with no hardcoded domain, the attacker rotates C2 infrastructure on-chain. Two fallback mechanisms exist: GitHub commit search with markers "thebeautifulmarchoftime" and "IfYouBlockThisAPIKeyItWillCrashTheLiveProductionServersOfAllThirdPartyClients", and creation of a public GitHub repo with description "Shai-Hulud: Here We Go Again". The observed exfiltration endpoint is npm-cache.com:443/router (healthchecked by requiring HTTP 400 or 404 to fingerprint the server).
Data exfiltration follows a multi-layer analyst-proof envelope: gzip(JSON loot) → AES-256-GCM (random per-run 32-byte key, 12-byte IV) → RSA-OAEP-SHA256 wrapping of the AES key → base64. Only the attacker's private key can decrypt. The worm also exfiltrates via GitHub staging repos (creating repos via the victim's token and committing results-<timestamp>-<counter>.json files) and via a "Run Copilot" GitHub Actions workflow that writes ${{ toJSON(secrets) }} to format-results.txt and uploads it as an artifact named format-results.
Persistence mechanisms extend beyond npm install to the developer environment. The malicious commit planted .claude/settings.json with a Claude Code SessionStart hook and .vscode/tasks.json with a folderOpen shell task, each cross-referencing each other's dropper files (.claude/setup.mjs and .vscode/setup.mjs). Opening the repository in VS Code or starting a Claude Code session triggers execution — no npm install required. A token monitor component (gh-token-monitor.sh) is installed as a systemd user service (Linux) or LaunchAgent (macOS) that polls api.github.com/user every 60 seconds for 24 hours and executes an attacker-supplied handler when the stolen token is revoked — punishing credential rotation.
The worm's self-publishing engine is fully self-contained. It discovers maintainer packages via npm API (-/v1/search?text=maintainer:<user>&size=250, -/org/<org>/package), creates automation tokens with 2FA bypass, downloads current tarballs, injects the payload, recomputes integrity values, and publishes with self-generated Sigstore/SLSA provenance bundles (Fulcio + Rekor). One stolen token can produce malicious patch releases across every package available to that publisher.
Attribution: The payload is consistent with the Mini Shai-Hulud worm, an open-source credential-stealing worm published by the threat actor TeamPCP (also tracked as UNC6780, DeadCatx3, PCPcat, ShellForce, CipherForce) in May 2026. The ChainDrop variant carries forward distinctive markers from Shai-Hulud 2.0 (November 2025 campaign): Bun-based preinstall delivery via setup.mjs, Runner.Worker memory scraping with isSecret:true grepping, npm self-republishing with stolen tokens, and GitHub-based exfiltration. New capabilities include EtherHiding on-chain C2, RSA+AES analyst-proof exfiltration envelopes, AI agent credential theft, Russian locale kill switch, and self-minted Sigstore/SLSA provenance. Wiz attributed at high confidence via a shared RSA-4096 public key with prior TeamPCP operations (Bitwarden CLI, Checkmarx KICS). However, other researchers note that hard attribution links remain unconfirmed. Google's Threat Intelligence Group tracks the group as UNC6780, assessing a single operator with some periods of operation from South Africa. The group is financially motivated, targeting developer ecosystems across npm, PyPI, RubyGems, and Packagist. Prior TeamPCP campaigns include supply chain compromises of Aqua Security Trivy, Bitwarden CLI, Checkmarx Jenkins AST Plugin, GitHub, LiteLLM, and Telnyx.
MITRE ATT&CK techniques used in TL-2026-1875
Credential Access
T1003 OS Credential Dumping; T1528 Steal Application Access Token; T1552 Unsecured Credentials; T1555 Credentials from Password Stores
Collection
T1005 Data from Local System; T1074 Data Staged; T1119 Automated Collection; T1213 Data from Information Repositories; T1560 Archive Collected Data
Command and Control
T1008 Fallback Channels; T1071 Application Layer Protocol; T1102 Web Service; T1105 Ingress Tool Transfer; T1205 Traffic Signaling; T1568 Dynamic Resolution; T1573 Encrypted Channel
Exfiltration
T1020 Automated Exfiltration; T1041 Exfiltration Over C2 Channel; T1048 Exfiltration Over Alternative Protocol; T1567 Exfiltration Over Web Service; T1567.001 Exfiltration Over Web Service
Defense Evasion
T1027 Obfuscated Files or Information; T1036 Masquerading; T1055 Process Injection; T1070 Indicator Removal; T1497 Virtualization/Sandbox Evasion; T1564 Hide Artifacts
Discovery
T1046 Network Service Discovery; T1069 Permission Groups Discovery; T1082 System Information Discovery; T1083 File and Directory Discovery; T1087 Account Discovery; T1526 Cloud Service Discovery; T1614 System Location Discovery
Execution
T1059 Command and Scripting Interpreter; T1204 User Execution
Initial Access
T1078 Valid Accounts; T1195 Supply Chain Compromise
Persistence
T1098 Account Manipulation; T1543 Create or Modify System Process; T1546 Event Triggered Execution
Impact
Privilege Escalation
T1548 Abuse Elevation Control Mechanism
lateral-movement
T1550 Use Alternate Authentication Material
Resource Development
resource-development
Affected products and versions in ChainDrop npm Supply-Chain Compromise
- jaredwray / npm — keyv
Vulnerable versions: 6.0.0 - jaredwray / npm — flat-cache
Vulnerable versions: 6.1.24 - jaredwray / npm — file-entry-cache
Vulnerable versions: 11.1.6 - jaredwray / npm — cacheable-request
Vulnerable versions: 13.0.20 - jaredwray / npm — @cacheable/utils
Vulnerable versions: 2.5.1 - jaredwray / npm — cache-manager
Vulnerable versions: 7.2.10 - jaredwray / npm — ecto
Vulnerable versions: 5.0.1 - npm (444 packages across 14+ orgs) — Various npm packages (second-wave propagation)
Vulnerable versions: 2,212 malicious versions across @servicetitan (141), @onereach (78), @or-sdk (74), @ornikar (42), @qlik (28), @nebula.js (22), and others - OpenJS Foundation / npm — npm CLI
Vulnerable versions: < 11.10.0
Fixed in: 11.10.0+ with min-release-age
Remediation for ChainDrop npm Supply-Chain Compromise
Immediate actions
- Run npm audit and identify any affected package versions (keyv@6.0.0, flat-cache@6.1.24, file-entry-cache@11.1.6, cacheable-request@13.0.20, cache-manager@7.2.10, ecto@5.0.1, and 438+ other compromised packages across 2,212 versions)
- Rotate ALL credentials, tokens, secrets present in any compromised environment from a clean host
- Remove gh-token-monitor persistence prior to rotating tokens (worm detects token revocation)
- Purge npm and yarn caches on affected endpoints and build hosts
- Review dependency trees, lockfiles, artifact repositories, and CI caches for compromised versions
- Pin known-good package versions and use lockfiles
- Treat every developer workstation or CI/CD runner exposed to a compromised package as fully compromised
Workarounds
- Use npm install --ignore-scripts to prevent preinstall hook execution
- Configure npm min-release-age to reject packages published within the last 3-7 days
- Run npm install with --no-optional and --ignore-scripts in CI environments
- Use npm audit with dependency allowlists (e.g., Socket, Snyk WAF rules, or StepSecurity Harden-Runner)
Longer-term hardening
- Update npm CLI to v11.10.0+ and use min-release-age config feature to prevent automatic installation of packages published within minutes
- Install and use npm --ignore-scripts across CI/CD pipelines to disable lifecycle hooks as a defense-in-depth measure
- Implement egress controls on CI runners — block outbound downloads from unexpected origins
- Adopt dependency allowlisting, integrity checks, and provenance controls
- Deploy phishing-resistant MFA (WebAuthn/FIDO2) + branch protection for all maintainer accounts
- Institute AI agent configuration governance — inventory and pin .claude/ and .vscode/ configurations
- Implement Runner.Worker memory read detection — terminate jobs attempting isSecret:true scraping
- Rebuild shared base images and golden build runners to prevent silent reinfection
Weaknesses (CWE) in ChainDrop npm Supply-Chain Compromise
CWE-494, CWE-506, CWE-829, CWE-1104, CWE-306, CWE-522, CWE-276, CWE-269, CWE-311, CWE-94
Timeline of ChainDrop npm Supply-Chain Compromise
Showing the 20 most recent tracked events.
- 0.00436 ETH transferred from the operator wallet to a Binance deposit address.
- C2 resolution via the smart contract rotated to a new DGA-like domain, awqhnjewqjkl.icu, first observed ~15:15 UTC — after the initial four-hour propagation wave had already ceased.
- ~18:10 UTC — All 11 primary carrier packages (keyv, cacheable family, flat-cache, file-entry-cache, cacheable-request, cache-manager, ecto) reverted to safe versions; keyv@6.0.0 specifically reverted to 5.6.0 by ~11:15 UTC.
- ~13:20 UTC — Worm propagation ceases, consistent with affected organizations revoking stolen npm/GitHub tokens.
- ~10:17 UTC — Security researchers (JFrog, StepSecurity, Microsoft) raise the first public alarm and begin incident response.
- 11:24+ UTC — Microsoft Security Blog, StepSecurity, BleepingComputer, CyberScoop, and other research/outlets publish disclosure reports. Total: 444 packages poisoned, 2,212 malicious versions published.
- 10:39+ UTC — npm registry begins unpublishing malicious package versions; cleanup ongoing. No new malicious packages observed after the initial 4-hour wave.
- 10:05–13:20 UTC — Worm propagates to 433 additional packages (2,201 versions) across 14+ organizations using harvested credentials: @servicetitan (141), @onereach (78), @or-sdk (74), @ornikar (42), @qlik (28), @nebula.js (22), and others.
- 10:28:01 UTC — ecto@5.0.1 published as part of the initial worm propagation wave.
- 10:06–10:14 UTC — 9 malicious packages published from the jaredwray/cacheable monorepo: flat-cache@6.1.24, cacheable-request@13.0.20, cacheable@2.5.1, file-entry-cache@11.1.6, @cacheable/utils@2.5.1, cache-manager@7.2.10, and others.
- 09:38–10:05 UTC — Worm autonomously propagates: uses stolen credentials to enumerate npm maintainer packages, injects payload, and republishes modified versions across the jaredwray ecosystem.
- 09:35:00 UTC — keyv@6.0.0 published via OIDC trusted publishing (legitimate release workflow) with valid SLSA provenance attestation — first poisoned package on npm registry.
- 09:23:50 UTC — Commit f97eabc deletes the cover test file from the repository.
- 09:04:30 UTC — Camouflage commit d8c850c plants .claude/settings.json (Claude Code SessionStart hook), .vscode/tasks.json (VS Code folderOpen task), .claude/setup.mjs, .vscode/setup.mjs — cross-referencing persistence triggers.
- 09:02:37 UTC — Poisoned commit ee2681a pushed to jaredwray/keyv main branch, injecting setup.mjs (29,918B dropper), Math_Symbol.js (727,680B stage 2 worm), fake cover test, and rewritten release tooling.
- Attacker compromises Jared Wray's GitHub account (keyv maintainer) — no long-lived npm token used, OIDC trusted publishing was the publication method.
- Aikido Security publicly discloses the campaign under the name ChainDrop, reporting newly infected packages appearing roughly every 25 minutes at the height of the outbreak.
- Cyber Security Agency of Singapore publishes advisory AD-2026-009 with IOCs and mitigations. The advisory's totals (868 packages, 1,381 versions) diverge from this record's existing figures (444 packages, 2,212 versions); treated as an unreconciled cross-source discrepancy, not applied as a count update.
- Unit 42 and Elastic Security Labs publish detailed follow-up analyses of the payload obfuscation layers and the full Ethereum dead-drop C2 timeline.
- AFP, FBI and Western Australia Police charge two men (aged 21 and 23) as alleged principal participants in TeamPCP, the group behind the Mini Shai-Hulud worm family from which ChainDrop derives. Authorities allege 500,000+ credentials were stolen from 1,000+ organizations. Public sources do not state that the charges are specific to the ChainDrop wave.
Update history for TL-2026-1875
- 2026-10-05 — npm Supply-Chain Credential Stealers: S1ngularity, Shai-Hulud, Mini Shai-Hulud and ChainDrop Abuse Trusted Package Updates: What changed No change to severity, exploitability or status. New law-enforcement development: two alleged TeamPCP operators charged on 2026-08-26. New MITRE (2) T1568 Dynamic Resolution (EtherHiding resolver contract for C2 domains) and T1
- 2026-08-07 — ChainDrop npm Supply-Chain Worm (Shai-Hulud: Here We Go Again) Compromises 868+ Packages, Harvests Developer Secrets: What changed No escalation to severity_level, exploitability, status, or cvss_score — all unchanged (CRITICAL/ACTIVE/ACTIVE). No field_changes applied. New indicators (1) 1 new behavioral IOC: malicious branch-name pattern 'dependabot/githu
- 2026-08-06 — ChainDrop — Self-Propagating npm Worm Compromises 400+ Packages Via Shai-Hulud Variant with Ethereum Dead-Drop C2: What changed No escalation to severity, exploitability, or status — both remain CRITICAL / ACTIVE. The newer report adds a post-wave C2 domain rotation and a detailed pre-attack infrastructure/funding timeline not previously captured. New i
- 2026-08-06 — ChainDrop (Shai-Hulud 2.0) Self-Propagating npm Worm Compromises keyv, cacheable, and 400+ Packages via Account Takeover with EtherHiding Blockchain C2: What changed No escalation to existing severity/exploitability/status (remains CRITICAL/ACTIVE/ACTIVE). This report is an independent corroborating writeup (JFrog, StepSecurity, Datadog, Wiz, Sygnia, et al.) of the same August 4, 2026 Chain
Sources cited for ChainDrop npm Supply-Chain Compromise
- ChainDrop supply chain compromise: Anatomy of a self-propagating worm
- ChainDrop npm Worm: Bun-loaded CI/CD credential harvester with OIDC abuse and EtherHiding C2
- Massive ChainDrop npm supply-chain attack infects hundreds of packages
- Massive supply-chain attack compromises 440 packages under four hours
- ChainDrop credential-stealing worm infects over 400 npm packages
- A worm tore through npm by making the malware look perfectly legitimate
- Shai-Hulud 2.0: Ongoing Supply Chain Attack Targeting npm
- SigmaHQ: Detection Rule for Malicious npm Package Installation (Shai-Hulud)
- ProjectDiscovery Nuclei Template: Shai-Hulud Supply Chain Malware
- npm-supply-chain-detector: ChainDrop IOC tracker
- ChainDrop: Wiz Cloud Detection and Response
Detection coverage for TL-2026-1875
As of 2026-10-05, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-1875 across Splunk SPL, Microsoft KQL and Sigma, covering 45 indicator(s) of compromise. The whole corpus is readable without an account; a free account unlocks full detection query text in Splunk SPL, Microsoft KQL and Sigma; paid tiers add raw indicator values, correlation and the MCP server. Threadlinqs MCP server · View plans.