Tracking Shai-Hulud: Inside the ChainDrop NPM Worm

Tracking Shai-Hulud: Inside the ChainDrop NPM Worm
ChainDrop is a self-propagating npm worm linked to TeamPCP that compromised a maintainer account, abused trusted GitHub Actions releases, and spread poisoned packages with valid provenance. It stole developer credentials, used an Ethereum smart contract for rotating C2 domains, and planted persistence hooks in IDE and AI-agent configuration files, while also threatening destructive deletion when tokens were revoked. #ChainDrop #TeamPCP #keyv #Sigstore #SLSA #Ethereum

Keypoints

  • ChainDrop entered the npm ecosystem on August 4, 2026 through a compromised maintainer account tied to the keyv ecosystem.
  • The worm abused GitHub Actions release pipelines to publish poisoned packages with valid SLSA and Sigstore provenance, including keyv 6.0.0.
  • It self-propagated by stealing npm tokens and republishing infected versions, spreading to more than 400 packages in under four hours.
  • Its command-and-control relied on an Ethereum smart contract, enabling domain rotation without changing the malware and bypassing blocklists.
  • The payload harvested a broad set of credentials, including npm, GitHub, cloud, Kubernetes, Vault, SSH, and AI tooling secrets.
  • Persistence was achieved through hooks in .claude/settings.json and .vscode/tasks.json, allowing re-execution when projects were opened in Claude Code or VS Code.
  • A revoked token could trigger destructive behavior such as remote code execution or wiping the victim’s home directory with rm -rf ~/.

MITRE Techniques

  • [T1195.002 ] Compromise Software Supply Chain – The attacker poisoned trusted release workflows and published malicious packages from legitimate repositories (‘the project’s existing GitHub Actions release workflow kicked in automatically, built the poisoned package, and published it’).
  • [T1059.007 ] JavaScript – The malware executed JavaScript payloads through setup.mjs and Math_Symbol.js (‘The setup.mjs file runs automatically’ and ‘The Math_Symbol.js file is a heavily obfuscated file executed by Bun’).
  • [T1053.005 ] Scheduled Task/Job: At – Persistence-like execution was triggered by IDE and agent hooks that re-ran the payload when projects were opened (‘Hooks VS Code to execute the payload when a project folder is opened’ and ‘Hooks Claude Code to execute node .vscode/setup.mjs at the start of a session’).
  • [T1105 ] Ingress Tool Transfer – The payload downloaded the Bun runtime from GitHub to run the second stage (‘Downloads the Bun JavaScript runtime v1.3.13 directly from its official GitHub release page’).
  • [T1555.003 ] Credentials from Web Browsers – The worm harvested tokens and credentials from configuration files, environment variables, and memory (‘targeting npm tokens from ~/.npmrc, environment variables, GitHub credentials such as PATs, … AWS credentials … SSH keys … AI tooling credentials’).
  • [T1552.001 ] Unsecured Credentials: Credentials In Files – It extracted secrets from files like ~/.npmrc, ~/.aws/credentials, ~/.kube/config, and ~/.ssh/ (‘targeting npm tokens from ~/.npmrc’ and ‘AWS credentials from ~/.aws/credentials’).
  • [T1041 ] Exfiltration Over C2 Channel – Stolen data was uploaded to attacker-controlled GitHub repositories and, if needed, retrieved via Ethereum-based C2 (‘create a new public repository under their identity’ and ‘calls an Ethereum smart contract … to retrieve active C2 domains’).
  • [T1568.002 ] Dynamic Resolution: Domain Generation Algorithms – The attacker rotated C2 domains through an Ethereum smart contract to evade blocklists (‘allowing the attacker to rotate domains with a single blockchain transaction’).
  • [T1486 ] Data Encrypted for Impact – Stolen data was compressed and encrypted before exfiltration (‘serialized to JSON, compressed, and encrypted using AES-256-GCM’).
  • [T1490 ] Inhibit System Recovery – Revocation of stolen tokens could trigger destructive behavior including deletion of the home directory (‘If the token returns a 4xx error … the worm triggers a secondary destructive payload’ and ‘wiping the victim’s entire home directory’).
  • [T1070.004 ] File Deletion: File Deletion – A destructive fallback used rm -rf ~/ to remove files (‘execute rm -rf ~/, wiping the victim’s entire home directory’).
  • [T1112 ] Modify Registry – The malware modified package.json and workflow/config files to ensure execution (‘modified package.json to add a preinstall hook’ and ‘plants execution hooks that target modern AI-assisted developer tooling’).

Indicators of Compromise

  • [MD5 ] Malware file hashes associated with the payload – f92ee93a0af971a3966bfa8efa9c2625, 57bcf8d9f6834c44450eac145a967d2f2, and 54140f7e17e6f97f83aa3472473e01add
  • [C2 URL ] Command-and-control endpoint used for fallback retrieval – https://npm-cache[.]com:443/router
  • [C2 domain ] Fallback and active C2 infrastructure – npm-cache[.]com, awqhnjewqjkl[.]icu
  • [Ethereum smart contract address ] EtherHiding C2 retrieval contract – 0xE1f2395ee43e45A1556EC6438a88c31B83493103
  • [File names ] Malicious and persistence-related files – setup.mjs, Math_Symbol.js
  • [Repository description strings ] Exfiltration repository naming used by the worm – Shai-Hulud: Here We Go Again, niagA oG eW ereH :duluH-iahS


Read more: https://www.zscaler.com/blogs/security-research/tracking-shai-hulud-inside-chaindrop-npm-worm