ChainDrop npm Worm Steals Developer Credentials and Uses Ethereum to Rotate C2

Summary
Unit 42 analyzed ChainDrop, an npm worm reported in over 400 packages. It steals developer and CI credentials, spreads through stolen publishing tokens and resolves C2 through Ethereum. Its operators remain unattributed.
Key points
- Unit 42 reports over 400 infected npm packages and observed execution in 10 environments. It found 453 matching public GitHub repositories across five candidate victim accounts; those accounts were not confirmed victims, and the repositories were later removed.
- Infected packages retain legitimate functionality while adding a preinstall hook, setup.mjs dropper and JavaScript payload executed through Bun. Stolen npm publishing tokens enable automated infection and republication of additional packages.
- The worm harvests cloud credentials, GitHub and npm tokens, SSH keys and other secrets. An embedded Python helper reads GitHub Actions Runner.Worker memory to extract temporary tokens and runner secrets.
- Developer-tool persistence uses cross-linked VS Code and Claude Code configurations, but only the VS Code path reaches the payload in the analyzed build. macOS LaunchAgent and Linux systemd persistence installers were present but not invoked.
- An Ethereum smart contract resolves C2 domains. Unit 42 observed an August 4, 2026 transaction rotating C2 from npm-cache[.]com to awqhnjewqjkl[.]icu without updating deployed malware; GitHub repositories provide additional exfiltration channels.
- An implemented but unobserved path targets a specific OpenSearch release workflow, exchanging OIDC tokens for npm publishing credentials and producing genuine Sigstore provenance for a modified package. Valid provenance alone therefore would not establish package safety.
- The code shares Shai-Hulud lineage, but Unit 42 could not attribute its operators to TeamPCP. Recommended containment includes credential rotation, removal of persistence and poisoned cached artifacts, and blocking both domain-based and GitHub-based exfiltration.
Article Details
- Attack Vectors
- Compromised npm packages execute setup.mjs through a preinstall hook, launching an obfuscated JavaScript payload with Bun while preserving legitimate package functionality.
- Stolen npm publishing tokens allow the worm to modify, increment and republish other packages accessible to the compromised account.
- GitHub Actions runners are targeted through process-memory scraping and a planted workflow that exports repository secrets as an Actions artifact.
- Developer-tool persistence uses VS Code folder-open tasks and Claude Code SessionStart hooks. In the analyzed build, only the VS Code path reaches the dropped payload.
- An implemented but unobserved repository-specific path targets release-drafter.yml in opensearch-project/opensearch-js, exchanges OIDC tokens for publishing credentials and adds the typosquatted dependency @opensearch/setup with genuine provenance.
- An Ethereum smart contract resolves C2 domains, with a GitHub commit-search backup mechanism. The domain-based exfiltration sender can evaluate attacker-supplied JavaScript responses, although no code was returned during the researchers' probe.
- Stolen GitHub tokens are double-Base64-encoded into public commit messages and retrieved by other worm instances.
- Defensive Notes
- Remove infected package versions and clear poisoned lockfiles, caches, mirrors and tarballs; restoring a clean latest tag does not remediate existing contaminated installations.
- Enumerate all packages writable by exposed npm credentials and review unexpected publishing activity and GitHub repository creation.
- Revoke or rotate exposed npm, GitHub, cloud, SSH, Kubernetes, Vault and AI-provider credentials; treat runners where the worm executed as potentially compromised.
- Remove all five dropped persistence files: .claude/math_init.js, .claude/settings.json, .claude/setup.mjs, .vscode/setup.mjs and .vscode/tasks.json.
- Hunt for gh-token-monitor LaunchAgent and systemd artifacts, but distinguish their latent installer capability from observed persistence.
- Block malicious domains using DNS or TLS SNI rather than shared Cloudflare edge IP addresses. Prefer sinkholing because the worm treats HTTP 400 and 404 responses as healthy.
- Monitor the Ethereum resolver contract for domain changes and address GitHub-based exfiltration as well as domain-based C2.
- Search commit history for IfYouBlockThisAPIKeyItWillCrashTheLiveProductionServersOfAllThirdPartyClients and revoke exposed credentials; inspect thebeautifulsnadsoftime records for planted backup C2 domains.
- Do not treat valid npm provenance as proof of clean content; investigate workflow identity and Rekor log entries.
- Use ephemeral CI runners, workload-bound authentication, canary credentials and restrictive CI egress policies.
- The 453 matching public repositories across five accounts are candidate compromise evidence, not confirmation that all five accounts were victims.
Indicators of compromise
| Type | Indicator | Context |
|---|---|---|
| DOMAIN | awqhnjewqjkl[.]icu | New C2 domain installed in the Ethereum resolver during the observed August 4, 2026 infrastructure rotation. |
| DOMAIN | js-mirror[.]com | Historical C2 domain previously returned by the attacker's Ethereum resolver contract. |
| DOMAIN | npm-cache[.]com | ChainDrop C2 and encrypted exfiltration domain used before the observed rotation. |
| DOMAIN | pypi-get[.]com | Historical C2 domain previously returned by the attacker's Ethereum resolver contract. |
| SHA256 | 54dc7ea54a1317cca0e890a2770630cf7fa6c97813e0cb9d2caa93012b350668 | SHA-256 of the first malicious setup.mjs dropper variant. |
| SHA256 | 9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc | SHA-256 of the ChainDrop Math_Symbol.js / math_init.js payload. |
| SHA256 | b27b82afa5f15512f3856e549fb83d873fd0049759a4b62ce64c8d7d4dc2c678 | SHA-256 of setup.mjs.malicious, a malicious dropper variant identified through a TLSH pivot. |
| SHA256 | fd3ca4007b225fdf8de7af4345a19179d5efa8c4bb9205f88cda806e5684b1eb | SHA-256 of the second malicious setup.mjs dropper variant. |
| URL | hxxp[:]//awqhnjewqjkl[.]icu/cdn-cgi/rum? | URL listed by the source as a C2 endpoint and probe path on the rotated malicious domain. |
| URL | hxxps[:]//npm-cache[.]com/router | Encrypted credential-exfiltration endpoint whose responses can supply JavaScript for evaluation. |
MITRE ATT&CK
T1005 · Data from Local SystemThe worm gathers local shell histories, wallet files, mount listings and application configuration alongside credentials.T1027 · Obfuscated Files or InformationThe JavaScript payload conceals strings and helper blobs using Base91, custom PBKDF2-based permutation and AES-256-GCM encryption.T1057 · Process DiscoveryThe Python memory scraper locates the Runner.Worker process on GitHub Actions runners.T1059.003 · Windows Command ShellObserved execution spawned cmd.exe from the JavaScript payload to invoke gh auth token.T1059.006 · PythonAn embedded Python helper searches GitHub Actions runner memory for OIDC tokens and runner secrets.T1059.007 · JavaScriptBun executes Math_Symbol.js or math_init.js to run the worm and harvest credentials.T1071.001 · Web ProtocolsThe domain-based sender transmits stolen data over HTTPS to /router and parses server responses for optional code execution.T1195.002 · Compromise Software Supply ChainChainDrop adds a dropper, payload and installation hook to legitimate npm packages and republishes them using compromised publishing credentials.T1528 · Steal Application Access TokenThe worm invokes gh auth token to retrieve the local GitHub CLI authentication token and also targets CI identity tokens.T1552.001 · Credentials In FilesThe payload collects credentials from .env, .netrc, developer configurations, Terraform state and other local files.T1552.004 · Private KeysChainDrop steals SSH keys from infected developer environments.T1552.005 · Cloud Instance Metadata APIThe worm queries cloud compute and container metadata endpoints to harvest temporary IAM role credentials.T1567.002 · Exfiltration to Cloud StorageStolen information is exported through public GitHub repositories and GitHub Actions artifacts.T1573.002 · Asymmetric CryptographyExfiltration envelopes wrap a random AES-256-GCM key using the operator's embedded RSA public key with RSA-OAEP-SHA256.T1614.001 · System Language DiscoveryBefore collecting data, the worm checks the host language and exits when Russian is detected.
Threat Actors
Malware
ChainDropChainDrop is a self-propagating npm worm that infected hundreds of packages, stole developer and cloud credentials, and republished itself through compromised npm tokens while also targeting GitHub Actions and AI codingShai-HuludIts operators used Ethereum-based C2 resolution and could silently rotate infrastructure without updating the malware, with evidence linking the campaign to Shai-Hulud-style tooling.
Vendors
Products
Bun[T1059.007 ] JavaScript – ChainDrop executes its payload through Bun and JavaScript dropper files to run the worm and launch credential theft (‘executes Math_Symbol.js or math_init.js via the bun nodejs runtime’).cacheable-requestThis includes malicious versions of widely used packages such as keyv and cacheable-request.Claude CodeThe malware establishes persistence through VS Code and Claude Code configuration files, with latent support for macOS LaunchAgents and Linux systemd services.Cortex XDRSome activity was detected by Palo Alto Networks products, including Koi Agentic Endpoint Security and Cortex XDR behavioral detections.GitHub Actionsand cloud credentials, and republished itself through compromised npm tokens while also targeting GitHub Actions and AI coding tool environments.keyvThis includes malicious versions of widely used packages such as keyv and cacheable-request.Koi Agentic Endpoint SecuritySome activity was detected by Palo Alto Networks products, including Koi Agentic Endpoint Security and Cortex XDR behavioral detections.npmChainDrop is a self-propagating npm worm that infected hundreds of packages, stole developer and cloud credentials, and republished itself through compromised npm tokens while also targeting GitHub Actions and AI codingVS CodeThe malware establishes persistence through VS Code and Claude Code configuration files, with latent support for macOS LaunchAgents and Linux systemd services.
