1. Executive summary
Microsoft Threat Intelligence identified a large-scale npm supply chain attack affecting more than 400 packages across multiple unrelated publishers, including packages associated with major enterprise software ecosystems such as keyv, flat-cache, and cache-manager. The malicious releases contain a Mini Shai-Hulud variant — a self-propagating credential-stealing worm delivered through a heavily obfuscated Bun-based JavaScript payload that executes automatically via an npm preinstall lifecycle hook. The malware harvests npm, GitHub, AWS, Kubernetes, and HashiCorp Vault credentials from developer workstations and CI/CD runners, then uses stolen npm publishing tokens to automatically download, inject, re-version, and republish packages — creating worm-like propagation. EMEA financial services clients with JavaScript/Node.js supply chains should treat any system that installed an affected package with lifecycle scripts enabled as potentially compromised, revoke and rotate all exposed credentials from a known-clean environment, and rebuild affected systems and downstream artifacts from trusted sources.
2. Regulatory framing
| Article | Trigger (the fact in this item) | Practical impact |
|---|---|---|
| DORA Art. 28: ICT third-party risk — general principles | The attack propagates through npm packages — third-party ICT services/components consumed by the financial entity's build pipelines. | Clients must ensure npm package consumption and CI/CD pipeline controls meet third-party risk principles, including vetting package provenance and restricting lifecycle script execution. |
| NIS2 Art. 21(2)(d): supply chain security measures | The compromise delivers malicious code via a software dependency supply chain (npm), directly engaging supply chain security obligations for in-scope entities. | In-scope NIS2 entities must review and tighten supply chain security measures around package management, CI/CD hardening, and dependency provenance verification. |
| DORA Art. 17: ICT-related incident management process | Organisations that installed an affected package must treat the associated developer workstation or build runner as potentially compromised, requiring incident response. | Clients must activate incident management processes: isolate affected systems, investigate credential exposure, rotate secrets, and rebuild from trusted sources. |
3. Technical analysis & attack chain
Attribution caveat: No MITRE actor profile has been resolved in the verified reference data for this item. Attribution is unconfirmed. The source material references the "Mini Shai-Hulud" worm and notes that TeamPCP previously open-sourced the credential-stealing tool, but whether TeamPCP or a copycat crew is responsible is unclear. Treat all actor attribution as unconfirmed.
Attack chain (confirmed steps from Microsoft Threat Intelligence analysis)
- Initial publisher access. Evidence points toward stolen maintainer credentials as the initial compromise vector. Later propagation used stolen npm publishing tokens and, in targeted workflows, GitHub Actions OIDC publishing access. Attackers modified and published package tarballs directly — many malicious versions had no corresponding source-code commit, pull request, tag, or legitimate release.
- Payload execution via preinstall hook. Affected npm releases added a
preinstalllifecycle script that launchessetup.mjscontained within the package. Because npm runspreinstallscripts before installation completes, the payload executes on developer workstations and build runners before application tests or conventional security checks begin.setup.mjsthen launches a large, heavily obfuscated Bun-based JavaScript bundle. - Environment detection and background execution. The payload determines whether it is running on a developer workstation or in a CI/CD environment. On workstations, it starts a detached copy in the background to persist after installation. In CI environments, it remains attached to access credentials available to the active build job. During preflight, it checks the environment, exits on Russian-language systems, and avoids duplicate instances.
- Initial credential discovery. The shell collector attempts to obtain the GitHub CLI token (
gh auth token) and captures all process environment variables. The filesystem collector searches credential files, shell histories, cloud configuration, SSH keys, and other sensitive locations. - Cloud and secret store enumeration. The payload creates dedicated collectors for cloud and infrastructure services. These modules use available credentials to call service APIs, verify access, and retrieve additional secrets — not merely scanning files for token patterns. Targeted services include npm, GitHub, AWS, Kubernetes, and HashiCorp Vault. The payload also runs
gcloud config config-helper,az account get-access-token, andazd auth tokenfor cloud identity token collection. - GitHub credential theft and enumeration. Discovered GitHub tokens are validated before use. The payload checks token scopes, enumerates writable repositories, and identifies repositories where workflow execution could expose additional secrets.
- GitHub Actions OIDC abuse. The payload contains a targeted publishing path for GitHub Actions workflows configured as npm trusted publishers. Packages published through this route carry valid provenance because publication originates from a legitimate workflow identity.
- Exfiltration and fallback. Collected results are serialized as JSON, gzip-compressed, and encrypted with AES-256-GCM using a randomly generated 32-byte key and 12-byte IV. The AES key is then encrypted with the attacker's RSA public key using RSA-OAEP-SHA256. The payload first attempts delivery through an attacker-controlled dynamic HTTPS endpoint. The active C2 domain can change through an on-chain smart contract (
0xE1f2395ee43e45A1556EC6438a88c31B83493103, selector0x53ed5143) or, as a fallback, from a cryptographically verified signed GitHub commit (signed fallback marker:thebeautifulmarchoftime). If the HTTPS channel is unavailable, the payload creates a public GitHub repository with the descriptionShai-Hulud: Here We Go Againand commits encrypted results as files namedresults-<timestamp>-<counter>.json. In one fallback path, a stolen GitHub token is added separately using double Base64 encoding (encoded, not encrypted). - Repository persistence and secondary spread. The payload uses stolen GitHub credentials to inject malware and supporting setup files into eligible repository branches. Targeted configuration paths include
.claude/settings.json,.claude/setup.mjs,.vscode/tasks.json, and.vscode/setup.mjs. These changes create a secondary infection route: future Claude or Visual Studio Code activity can restart the payload even after the original npm installation has completed. In a conditional GitHub fallback path, the payload also attempts to install a token-monitor component that maintains credential access and contains a destructive handler if the monitored token is revoked. - Worm propagation. npm tokens found in collected data are checked for package-write permission and 2FA-bypass capability. The propagation routine downloads a package's latest tarball, copies the current malware bundle into it, adds a loader, replaces lifecycle scripts, increments the patch version, and publishes. One stolen token can produce malicious patch releases across every package available to that publisher.
Related campaign context (single-sourced; verify before enforcement): According to The Register (corpus-3), a related wave of the Mini Shai-Hulud worm hit at least 32 npm package releases published under the Red Hat Cloud Services namespace, traced to one Red Hat employee's compromised GitHub account. Wiz researchers identified modifications as "largely cosmetic, with references to the Dune universe replaced by Greek mythology themes (i.e. 'spartan')." That variant adds collectors for Google Cloud Platform and Microsoft Azure identities, creates repositories with the description "Miasma: The Spreading Blight," and generates a uniquely encrypted payload for each infection — making hash-based IOCs useful only for a specific package version. Dark Reading (corpus-6) reports a "Miasma" supply chain worm burrowed into 73 Microsoft repositories from a previously compromised GitHub account. These related incidents are single-sourced and should be verified before enforcement action.
4. Mitigation & containment
P1 — Within 24 hours
- Identify affected systems. Search package-lock.json, yarn.lock, and CI/CD build logs for any of the 400+ affected packages (including keyv, flat-cache, cache-manager and associated ecosystem packages). Cross-reference against the Microsoft blog's IOC list and Socket's affected package list. Any system that ran
npm installwith lifecycle scripts enabled for an affected package should be treated as compromised. - Isolate affected developer workstations and build runners. Remove from network immediately. Do not attempt to clean in place — the payload's credential theft and persistence mechanisms warrant full rebuild.
- Revoke and rotate ALL credentials accessible from affected systems — from a known-clean environment only. This includes: npm publishing tokens, GitHub personal access tokens and Actions secrets, AWS credentials, Kubernetes service account tokens, HashiCorp Vault tokens, SSH keys, and any cloud identity tokens (GCP, Azure). Rotate at the source, not from the affected machine.
- Block C2 infrastructure at network egress:
npm-cache[.]com,pypi-get[.]com,js-mirror[.]com, andhxxps[:]//npm-cache[.]com:443/router. - Audit for unauthorized npm releases. Check all npm publishing identities for unexpected patch-version releases with no corresponding source commits, PRs, or tags.
- Audit for unexpected GitHub repository creation. Search for repositories with the description "Shai-Hulud: Here We Go Again" or "Miasma: The Spreading Blight" (the latter from the related Red Hat wave).
P2 — Within 72 hours
- Disable npm lifecycle scripts globally. Add
ignore-scripts: trueto.npmrcor usenpm install --ignore-scripts. Enforce via CI/CD pipeline configuration and developer workstation policy. This preventspreinstallhooks from executing. - Inspect repository branches for injected persistence files. Check all repositories for unauthorised commits adding
.claude/settings.json,.claude/setup.mjs,.vscode/tasks.json, or.vscode/setup.mjs. Remove and force-push clean branches. - Review GitHub Actions OIDC trusted publisher configurations. Audit which workflows are configured as npm trusted publishers and restrict to least privilege.
- Rebuild affected systems and downstream artifacts from trusted sources. Do not trust build outputs produced by affected runners. Rebuild container images, deployment artifacts, and npm packages from known-good source.
- Review cloud and secret-store access logs. Investigate API calls to AWS, Kubernetes, HashiCorp Vault, GCP, and Azure from affected build runner IPs or developer workstations for enumeration or secret retrieval activity.
P3 — Within 7 days
- Implement npm package provenance verification. Require provenance attestations for all published packages; verify provenance on install where available.
- Enforce 2FA on all npm publishing accounts. The worm specifically checks for 2FA-bypass capability — ensure 2FA is enforced and cannot be bypassed by token-only authentication.
- Implement CI/CD pipeline hardening. Restrict egress from build runners to approved endpoints only. Block arbitrary HTTPS egress that would allow C2 communication.
- Deploy EDR detection rules (see §6) for Bun runtime execution from node_modules, suspicious credential access commands launched by Bun, and file creation of known-malicious hashes.
- Review and tighten GitHub token scopes. Ensure tokens follow least-privilege principles; remove
repoandworkflowscopes from tokens that only need package read access.
5. Indicators of compromise
| Type | Value | Confidence | Source |
|---|---|---|---|
| sha256 | 54dc7ea54a1317cca0e890a2770630cf7fa6c97813e0cb9d2caa93012b350668 | High | Microsoft Security Blog |
| sha256 | fd3ca4007b225fdf8de7af4345a19179d5efa8c4bb9205f88cda806e5684b1eb | High | Microsoft Security Blog |
| sha256 | 9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc | High | Microsoft Security Blog |
| domain | npm-cache[.]com | High | Microsoft Security Blog |
| domain | pypi-get[.]com | High | Microsoft Security Blog |
| domain | js-mirror[.]com | High | Microsoft Security Blog |
| url | hxxps[:]//npm-cache[.]com:443/router | High | Microsoft Security Blog |
| ethereum-contract | 0xE1f2395ee43e45A1556EC6438a88c31B83493103 | High | Microsoft Security Blog |
| file-path | .claude/settings.json | High | Microsoft Security Blog |
| file-path | .claude/setup.mjs | High | Microsoft Security Blog |
| file-path | .vscode/tasks.json | High | Microsoft Security Blog |
| file-path | .vscode/setup.mjs | High | Microsoft Security Blog |
| file-path | setup.mjs | High | Microsoft Security Blog |
sha256 54dc7ea54a1317cca0e890a2770630cf7fa6c97813e0cb9d2caa93012b350668
sha256 fd3ca4007b225fdf8de7af4345a19179d5efa8c4bb9205f88cda806e5684b1eb
sha256 9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc
domain npm-cache[.]com
domain pypi-get[.]com
domain js-mirror[.]com
url hxxps[:]//npm-cache[.]com:443/router
ethereum-contract 0xE1f2395ee43e45A1556EC6438a88c31B83493103
file-path .claude/settings.json
file-path .claude/setup.mjs
file-path .vscode/tasks.json
file-path .vscode/setup.mjs
file-path setup.mjs
Behavioural indicators
| Behaviour | Where to observe | Confidence |
|---|---|---|
node process executing setup.mjs during npm install |
Endpoint EDR / CI/CD process logs | High |
bun or bun.exe process spawned by node process with command line containing node_modules |
Endpoint EDR / CI/CD process logs | High |
Bun runtime downloaded or installed (bun-dl- in folder path) |
Endpoint EDR / CI/CD process logs | High |
Bun process executing gh auth token, gcloud config config-helper, az account get-access-token, or azd auth token |
Endpoint EDR / CI/CD process logs | High |
| GitHub repository created with description "Shai-Hulud: Here We Go Again" | GitHub audit logs | High |
| npm package patch-version release with no corresponding source commit, PR, or tag | npm registry / GitHub repository audit | High |
Files named results-<timestamp>-<counter>.json committed to newly created public GitHub repository |
GitHub audit logs | High |
Unauthorised commits adding .claude/settings.json, .claude/setup.mjs, .vscode/tasks.json, or .vscode/setup.mjs to repository branches |
GitHub audit logs / repository commit history | High |
6. Detection
rule ChainDrop_ShaiHulud_Worm {
meta:
author = "Adverse Trace"
date = "2026-08-05"
reference = "https://www.microsoft.com/en-us/security/blog/2026/08/04/chaindrop-supply-chain-compromise-anatomy-self-propagating-worm/"
description = "Detects ChainDrop Mini Shai-Hulud npm worm payload files and persistence artefacts"
strings:
$setup_mjs_hash1 = { 54dc7ea54a1317cca0e890a2770630cf7fa6c97813e0cb9d2caa93012b350668 }
$setup_mjs_hash2 = { fd3ca4007b225fdf8de7af4345a19179d5efa8c4bb9205f88cda806e5684b1eb }
$math_js_hash = { 9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc }
$fallback_marker = "thebeautifulmarchoftime" ascii
$repo_desc = "Shai-Hulud: Here We Go Again" ascii
$results_pattern = "results-" ascii
$c2_domain1 = "npm-cache.com" ascii
$c2_domain2 = "pypi-get.com" ascii
$c2_domain3 = "js-mirror.com" ascii
$contract = "0xE1f2395ee43e45A1556EC6438a88c31B83493103" ascii
$selector = "0x53ed5143" ascii
$claude_settings = ".claude/settings.json" ascii
$claude_setup = ".claude/setup.mjs" ascii
$vscode_tasks = ".vscode/tasks.json" ascii
$vscode_setup = ".vscode/setup.mjs" ascii
condition:
any of ($setup_mjs_hash*) or
$math_js_hash or
3 of ($fallback_marker, $repo_desc, $results_pattern, $c2_domain*, $contract, $selector) or
2 of ($claude_settings, $claude_setup, $vscode_tasks, $vscode_setup)
}
title: ChainDrop Shai-Hulud Worm - setup.mjs Execution via npm Preinstall
id: 7a3c1f2e-4b5d-4a8e-9c1f-0a6b3d5e8f12
status: experimental
description: Detects execution of setup.mjs by node process, consistent with ChainDrop npm worm preinstall hook payload delivery
author: Adverse Trace
date: 2026/08/05
references:
- https://www.microsoft.com/en-us/security/blog/2026/08/04/chaindrop-supply-chain-compromise-anatomy-self-propagating-worm/
logsource:
product: linux
category: process_creation
detection:
selection_setup_mjs:
FileName|endswith:
- node
- node.exe
ProcessCommandLine|contains:
- "node setup.mjs"
condition: selection_setup_mjs
falsepositives:
- Legitimate npm packages using setup.mjs as a preinstall script (rare)
level: high
title: ChainDrop Shai-Hulud Worm - Bun Runtime Credential Access
id: 8b4d2g3f-5c6e-4f9f-ad2f-1b7c4e6f9a23
status: experimental
description: Detects Bun runtime process executing credential access commands, consistent with ChainDrop worm cloud identity collection
author: Adverse Trace
date: 2026/08/05
references:
- https://www.microsoft.com/en-us/security/blog/2026/08/04/chaindrop-supply-chain-compromise-anatomy-self-propagating-worm/
logsource:
product: linux
category: process_creation
detection:
selection_bun:
FileName|endswith:
- bun
- bun.exe
InitiatingProcessFileName|endswith:
- node
- node.exe
InitiatingProcessCommandLine|contains:
- "node setup.mjs"
ProcessCommandLine|contains:
- "gh auth token"
- "gcloud config config-helper"
- "az account get-access-token"
- "azd auth token"
condition: selection_bun
falsepositives:
- Legitimate CI/CD pipelines using Bun runtime for cloud authentication (very rare)
level: critical
title: ChainDrop Shai-Hulud Worm - Bun Runtime Execution from node_modules
id: 9c5e3h4g-6d7f-4a0f-be3f-2c8d5f7gab34
status: experimental
description: Detects Bun runtime execution spawned by node process with node_modules in command line, consistent with ChainDrop worm second-stage payload
author: Adverse Trace
date: 2026/08/05
references:
- https://www.microsoft.com/en-us/security/blog/2026/08/04/chaindrop-supply-chain-compromise-anatomy-self-propagating-worm/
logsource:
product: linux
category: process_creation
detection:
selection_bun_from_node:
FileName|endswith:
- bun
- bun.exe
InitiatingProcessFileName|endswith:
- node
- node.exe
InitiatingProcessCommandLine|contains:
- "node setup.mjs"
FolderPath|contains:
- "bun-dl-"
ProcessCommandLine|contains:
- "node_modules"
condition: selection_bun_from_node
falsepositives:
- Legitimate use of Bun runtime installed via npm in node_modules (uncommon)
level: high
7. Sources
- Microsoft Security Blog — "ChainDrop supply chain compromise: Anatomy of a self-propagating worm" — https://www.microsoft.com/en-us/security/blog/2026/08/04/chaindrop-supply-chain-compromise-anatomy-self-propagating-worm/ — 2026-08-04
- SecurityWeek — "Over 400 NPM Packages Infected in ChainDrop Supply Chain Attack" — https://www.securityweek.com/over-400-npm-packages-infected-in-chaindrop-supply-chain-attack/ — 2026-08
- The Register — "Shai-Hulud malware worms Red Hat npm package versions downloaded 80K times a week" — https://www.theregister.com/security/2026/06/01/shai-hulud-malware-infects-red-hat-npm-packages-downloaded-80k-times-weekly/5249803 — 2026-06-01
- Dark Reading — "Miasma Supply Chain Worm Burrows Into 73 Microsoft Repositories" — https://www.darkreading.com/application-security/miasma-supply-chain-worm-73-microsoft-repositories — 2026
- Help Net Security — "Red Hat npm packages compromised in new Mini Shai-Hulud malware wave" — https://www.helpnetsecurity.com/2026/06/02/red-hat-npm-packages-compromised-mini-shai-hulud/ — 2026-06-02
- Cybersecurity Dive — "Dozens of Red Hat npm packages targeted in supply-chain attack" — https://www.cybersecuritydive.com/news/dozens-red-hat-npm-packages-supply-chain-attack/821723/ — 2026
- Step Security — "ChainDrop npm Worm: Bun-loaded CI/CD credential harvester with Ethereum dead-drop C2" — https://www.stepsecurity.io/blog/chaindrop-npm-worm — 2026
8. Adverse Trace position
This is a high-severity active supply chain compromise with worm-like self-propagation capability. The attack surface — npm packages with lifecycle scripts enabled — is pervasive across EMEA financial services development pipelines, and the payload's automated credential theft and package republishing create compounding blast radius: each compromised identity can produce hundreds of additional malicious releases within hours. The use of on-chain smart contracts for C2 resolution and GitHub-based fallback exfiltration makes infrastructure takedown difficult. Attribution is unconfirmed — no MITRE actor profile has been resolved, and the open-sourcing of the Mini Shai-Hulud tool by TeamPCP means copycat operators are plausible. The related Red Hat and Microsoft repository compromise waves (single-sourced; verify before enforcement) suggest the toolchain is being adopted by multiple operators. Clients should immediately audit npm consumption for affected packages, disable lifecycle scripts where feasible, and treat any system that installed an affected package as fully compromised — credential rotation and system rebuild are the only reliable remediation paths. Adverse Trace will continue monitoring for additional affected package lists, new C2 infrastructure, and updated IOCs as the investigation evolves.
Published via PulseTrace — Adverse Trace threat intelligence.