Shai-Hulud V2 is an advanced supply chain campaign that abused the npm ecosystem to compromise over 700 packages, create 27,000+ malicious GitHub repositories, and expose roughly 14,000 secrets across hundreds of organizations. It leverages preinstall execution, Bun-based payloads, self-hosted GitHub Actions runners, cross-victim credential recycling, and a destructive dead manâs switch to maximize persistence, propagation, and data exfiltration. #ShaiHulud #npm
Keypoints
- Shai-Hulud V2 infected over 700 npm packages within hours and created more than 27,000 malicious GitHub repositories, exposing ~14,000 secrets across 487 organizations.
- The campaign shifted from postinstall to preinstall lifecycle execution, allowing payload execution even when installs fail and increasing impact.
- V2 adopts the Bun runtime with a small dropper (setup_bun.js) and a large obfuscated payload (bun_environment.js) for stealth and evasion.
- Stolen credentials (GitHub PATs, npm tokens, cloud keys) are validated and reused to publish infected packages, create repositories, and register self-hosted GitHub Actions runners for persistence.
- Data exfiltration is performed by uploading encoded files (contents.json, environment.json, cloud.json, truffleSecrets.json, actionsSecrets.json) to attacker-created GitHub repos to blend with legitimate traffic.
- Cross-victim credential recycling lets the malware find tokens in previously created repos, creating a botnet-like propagation and resilience against token revocation.
- A dead manâs switch can trigger destructive wiping (cipher/shred) if access to GitHub and npm is lost, risking mass data destruction across infected hosts.
MITRE Techniques
- [T1195 ] Supply Chain Compromise â Compromised and published malicious updates to npm packages to propagate the malware (âcompromised over 700 npm packagesâ).
- [T1059 ] Command and Scripting Interpreter â Uses JavaScript dropper and payload scripts (setup_bun.js, bun_environment.js) and executes shell commands to install runtimes and runners (âsetup_bun.js dropper script performs several functions⌠Launches the obfuscated payload (bun_environment.js) as a detached background process.â)
- [T1105 ] Ingress Tool Transfer â Downloads and installs Bun and the official GitHub Actions runner to the host to enable execution and persistence (âDownloads and installs Bun using official installersâ / âDownloads the official GitHub Actions runner (v2.330.0).â)
- [T1543 ] Create or Modify System Process â Installs and starts self-hosted GitHub Actions runners (SHA1HULUD) as background processes to maintain persistent remote execution (âRegisters the runner under the name SHA1HULUD⌠Starts the runner as a background process.â)
- [T1552 ] Unsecured Credentials â Harvests tokens from environment variables and files, including npm tokens in .npmrc and GitHub tokens in env vars (âExtracts npm authentication tokens from .npmrc files.â / âSearches for Personal Access Tokens (ghp_) and OAuth tokens (gho_) within environment variables.â)
- [T1078 ] Valid Accounts â Uses stolen/validated GitHub and npm tokens to publish infected packages, create repositories, and register runners (âpublishes the infected version using the stolen tokenâ / âCreates a runner registration token via the GitHub APIâ).
- [T1567 ] Exfiltration Over Web Service â Exfiltrates stolen data to attacker-controlled GitHub repositories and uploads files encoded to evade detection (âstolen data is exfiltrated to GitHub repositories that are created using compromised tokensâ).
- [T1485 ] Data Destruction â Implements a dead manâs switch that overwrites and deletes user files using cipher (Windows) and shred (Linux/macOS) if containment is detected (âdead manâs switch initiates data destruction across the compromised system using cipher and shredâ).
- [T1082 ] System Information Discovery â Detects CI/CD environments and collects environment variables and system metadata to drive environment-aware behavior (âDetected via environment variables such as GITHUB_ACTIONS, BUILDKITE, CIRCLE_SHA1, CODEBUILD_BUILD_NUMBER, and PROJECT_ID.â / âComplete dump of process.env, containing all environment variables.â)
Indicators of Compromise
- [Files & directories ] Malicious payloads and workflows â setup_bun.js, bun_environment.js, .github/workflows/discussion.yaml, and exfiltrated files like cloud.json, contents.json (and other exfiltrated filenames such as environment.json, truffleSecrets.json).
- [File hashes ] Known malicious binaries â SHA256 of setup_bun.js: a3894003ad1d293ba96d77881ccd2071446dc3f65f434669b49b3da92421901a; bun_environment.js: 62ee164b9b306250c1172583f138c9614139264f889fa99614903c12755468d0 (and 1 more bun_environment.js hash).
- [GitHub indicators ] Repository and workflow patterns â repository description âSha1-Hulud: The Second Coming.â or âSha1-Hulud: The Continued Comingâ, random 18-character repository names (e.g., zl8cgwrxf1ufhiufxq), workflow path .github/workflows/discussion.yaml, and self-hosted runner name SHA1HULUD.
- [NPM packages ] Impacted package names â examples include zapier-platform-core, @ensdomains/ensjs, posthog-js, @postman/tunnel-agent, @asyncapi/generator (and dozens of other compromised packages across the ecosystem).
- [Artifacts & exfiltrated files ] Evidence of data theft â contents.json (system info and token metadata), environment.json (process.env dump), cloud.json (cloud secret manager data), truffleSecrets.json (TruffleHog scan results), actionsSecrets.json (GitHub Actions secrets).
Read more: https://www.zscaler.com/blogs/security-research/shai-hulud-v2-poses-risk-npm-supply-chain