Shai-Hulud Supply Chain Attack
#04HIGH/ FirewallFables/ Oct 10, 2026/ 8 min read
Jump to section
- 011 Introduction
- 022 Timeline of the Shai-Hulud npm Supply-Chain Attacks
- 033 Attack Flow (How the Worm Spread)
- 043.1 Stage 1: Initial Compromise - Acquiring Maintainer Credentials
- 053.2 Stage 2: Publishing Infected Packages
- 063.3 Stage 3: Payload Execution & Credential Harvesting
- 073.4 Stage 4: Exfiltration & Public Disclosure / Back-Channeling
- 083.5 Stage 5: Propagation - Self-Replicating Behavior (Worm-like Spread)
- 093.6 Stage 6: Persistence & Long-Term Access (CI/CD Backdoors)
- 103.7 Stage 7: Fail-Safe / Destructive Behavior (if Detection Occurs)
- 114 Simulated Supply-Chain Compromise via PyPI Test Repository
- 124.1 Environment Setup
- 135 Attack Flow Demonstration
- 14Package Development
- 15Publishing to a Test Repository
- 16Listener Preparation (Attacker Side)
- 17Package Installation (Victim Side)
- 18Callback Received & Logged
- 196 Conclusion
#1 Introduction
The recent discovery of the "Shai-Hulud" worm in the npm ecosystem highlights a growing weakness in the way modern software is built and distributed. Named after the sandworm from Dune, this malware spreads not by exploiting classic system vulnerabilities, but by abusing trust in open-source software packages. In its initial wave, attackers managed to compromise over 180 npm libraries, turning legitimate developer dependencies into carriers of malicious code. The real danger lies in its self-spreading behavior—once a developer's npm or GitHub token is stolen, the worm automatically infects and republishes other packages owned by the same maintainer, allowing the attack to grow rapidly.
Since many developers use Linux and macOS to build applications, those environments became key targets in this campaign. Some malware versions even include secret-scanning abilities using existing open-source tools like TruffleHog to extract deeper credentials, including cloud and internal keys. To maintain long-term access, attackers modify GitHub Actions settings, add unauthorized workflow files, and sometimes register infected machines as self-hosted runners, giving them remote execution control. This incident serves as a strong reminder that software supply-chain security must consider not only the code we write, but also the code we import, install, and allow to run during build and deployment processes.
#2 Timeline of the Shai-Hulud npm Supply-Chain Attacks
- August 2025 - Early npm-ecosystem compromises involving developer account and token theft show a rising pattern of dependency poisoning, setting the stage for later worm-driven attacks.
- 15 September 2025 - Security researchers detect the first Shai-Hulud worm activity inside the npm package registry. Initial investigation confirms compromise of over 180 npm packages.
- 17 - 23 September 2025 - Multiple security vendors release warnings and publish Indicators of Compromise (IOCs), including attacker-generated GitHub repositories used to store and expose stolen secrets, often disguised using package-maintainer names or campaign-style labels.
- October 2025 - Deeper analysis reveals that certain malicious packages include automated secret-scanning modules, leveraging open-source tools like TruffleHog to extract developer, CI/CD, and cloud credentials (AWS, GCP, Azure). Attackers also begin modifying GitHub Actions workflow files to maintain long-term remote access and persistence.
- 21 - 24 November 2025 (Shai-Hulud 2.0) - A much more aggressive variant, referred to as Shai-Hulud 2.0, is deployed. This version abuses npm install lifecycle scripts (preinstall/postinstall), allowing malware execution earlier in the package installation process. The campaign infects hundreds of packages rapidly within hours, spreading automatically using stolen maintainer tokens.
- Late November 2025 - Ecosystem Impact & Response - The infection radius expands to tens of thousands of GitHub repositories, affecting both developer endpoints and CI/CD build environments. Organizations and vendors investigate downstream exposure, revoke compromised runners, remove unauthorized workflow files, rotate leaked secrets, publish mitigation guidance. Several major platforms confirm brief package-level compromise, reinforcing the systemic risk of transitive dependency trust.
#3 Attack Flow (How the Worm Spread)
#3.1 Stage 1: Initial Compromise - Acquiring Maintainer Credentials
- The attackers begin by targeting maintainers or developers often via phishing campaigns or social-engineering designed to steal npm/GitHub credentials or personal access tokens (PATs).
- Once they acquire valid tokens (npm auth tokens or GitHub PATs), they obtain full publishing privileges for one or more npm packages maintained by the compromised account.
- This initial foothold does not rely on a vulnerability in npm itself, but on compromising human trust. Maintainers are tricked or compromised, giving attackers legitimate access. At this point, the attacker has a "trusted identity" inside the npm ecosystem.
#3.2 Stage 2: Publishing Infected Packages
- Using the stolen credentials, attackers publish malicious versions of legitimate npm packages (or even new packages) under the maintainer's name.
- The malicious versions include lifecycle scripts (initially postinstall, in the later 2.0 wave sometimes preinstall) that will execute automatically when the package is installed.
- This means unsuspecting developers who npm install the package or automated CI/CD pipelines that build the project will trigger the malicious code without needing to consciously "run malware."
#3.3 Stage 3: Payload Execution & Credential Harvesting
Once the malicious package is installed:
- The embedded script executes automatically (via postinstall or preinstall). In earlier versions, postinstall was used; in 2.0, attackers shifted to preinstall to maximize stealth and early execution.
- The payload inspects the environment for secrets/credentials including:
- npm tokens
- GitHub tokens / Personal Access Tokens (PATs)
- SSH keys
- Cloud provider credentials (AWS, GCP, Azure) — including metadata-based credentials if available.
- In many cases, the malware uses specialized secret-scanning tools (e.g. TruffleHog) to dig deep into local files, commit histories, environment variables etc., in search of any sensitive credential material.
- Once secrets are harvested, the malware prepares them for exfiltration — often encoding them (e.g. double-base64) and packaging them into files like data.json, cloud.json, environment.json, etc.
#3.4 Stage 4: Exfiltration & Public Disclosure / Back-Channeling
The worm employs several exfiltration mechanisms to siphon credentials and data out - while hiding in plain sight:
- It uses the stolen GitHub token (or other credentials) to create a public GitHub repository with a name like "Shai-Hulud" (or "Shai-Hulud: The Second Coming") and pushes the harvested secrets (encoded) there.
- In some variants (particularly the initial wave), a webhook-based exfiltration was included - a GitHub Actions workflow or direct webhook POST to attacker-controlled endpoint (e.g. webhook[.]site). Even if webhook endpoints were disabled later, the public GitHub repo still retained the stolen data.
- The choice of GitHub as exfil destination is strategic: because developers and teams often interact with GitHub, such activity may not trigger suspicion; exfiltration blends with normal development traffic.
#3.5 Stage 5: Propagation - Self-Replicating Behavior (Worm-like Spread)
What makes Shai-Hulud particularly evil is its ability to self-replicate and spread without further manual intervention:
- After stealing a maintainer's npm token, the worm authenticates as that maintainer and repackages other npm libraries under their control - injecting the same malicious code and publishing new trojanized versions.
- This creates a cascading compromise: each infected package acts as a launchpad to infect additional packages (transitive dependencies), libraries, and downstream projects.
- In the 2.0 wave especially, the scale expanded dramatically - hundreds (even 700-800+) packages were backdoored within hours. Reports indicate thousands of GitHub repos were affected; some vendors estimate tens of thousands.
#3.6 Stage 6: Persistence & Long-Term Access (CI/CD Backdoors)
Beyond initial infection, the attackers aim to maintain long-term control and ability to re-infect or exfiltrate further:
- The malicious payload often installs a runtime (in 2.0, via Bun) to help run the code more stealthily and reliably across environments.
- Then, the worm pushes malicious GitHub Actions workflow files into repositories (or new ones) - enabling remote code execution, credential harvesting, and exfiltration each time the CI/CD pipeline runs.
- In some cases, the malware also registers self-hosted GitHub runners under attacker control or uses compromised infrastructure to ensure persistence even if a package is later removed.
- Because exfiltration and propagation use legitimate npm/GitHub APIs and user credentials, many detection tools - especially those focused only on known bad hashes or static analysis - fail to catch these actions.
#3.7 Stage 7: Fail-Safe / Destructive Behavior (if Detection Occurs)
- Some variants of Shai-Hulud 2.0 include a destructive fallback: if the malware detects it's being analyzed, or fails to exfiltrate credentials, it may attempt to delete user data — for example, wiping the user's home directory to disrupt forensic investigation and cause damage.
- This increases risk beyond just credential theft: a failed containment could lead to data loss or ransomware-like conditions, especially on developer or build machines containing critical code, configuration, or internal secrets.
#4 Simulated Supply-Chain Compromise via PyPI Test Repository
To show how a supply-chain compromise works in practice, a simulation was performed in an isolated and controlled environment. A Python package was created and published to a test PyPI repository, mimicking the scenario where a trusted dependency becomes a malware carrier. The goal of the demonstration was not to harm systems, but to observe the risk and validate detection principles in a lab setting.
#4.1 Environment Setup
- Development System: Ubuntu (isolated VM)
- Package Type: Custom Python utility library built with simple function such as addition and published to a test PiPy repo using twine utility
- Attacker System: KaliLinux VM running a local reverse-shell listener (Netcat)
- Victim System: Ubuntu VM was used as victim/client VM where the package would be installed using pip for exploitation.
#5 Attack Flow Demonstration
The simulation followed these steps:
#Package Development
- A Python library was created locally and structured as a normal pip-installable module.
- A reverse shell payload was included to the instance method init.py to initiate a test callback to the attacker listener for proof-of-concept. The helper function contained two simple functions such as addition and reverse string.
#Publishing to a Test Repository
- The package was built and uploaded to PyPI test index using twine utility.
- The repository existed only inside the lab, ensuring that no external users or real systems were exposed.
#Listener Preparation (Attacker Side)
- The attacker VM launched a Netcat listener locally to accept the callback.
- The callback simulated what a real reverse shell C2 trigger could look like, without delivering a command shell or enabling post compromise actions.
#Package Installation (Victim Side)
- The package was installed on a separate Ubuntu VM using pip.
- Once installed, the package functions were imported(add, rev string) for the normal usage in a python code, On executing the python file it initiated a connection request to the attacker listener.
#Callback Received & Logged
- The attacker listener captured the package-initiated connection, confirming the simulation success.
- Multiple command executions can be seen from the attacker's terminal confirming the attack was successful.
#6 Conclusion
The Shai-Hulud 2.0 attack shows that trusting third-party dependencies without verification remains one of the biggest risks in software security. What began as stolen developer tokens escalated into one of the fastest and most disruptive automated supply-chain infections seen in the npm ecosystem.
Pass it on
More fables
Harbor Default Credentials: A Case Study in Container Registry Security
An exposed container registry with default credentials hands an attacker the entire software supply chain — images, secrets, source code.
No Auth, 164 Million Records: The Malawi Credit Bureau Exposure
A Kibana dashboard with zero authentication exposed the entire Malawian credit bureau — 2.4 million full identity profiles, 49 million loan records and live application logs — to anyone who knew the IP.
The Registry That Called Everyone: 265 Million Numbers Exposed at India's DND
Two unauthenticated CouchDB nodes held India's entire Do-Not-Disturb registry — 245 million phone preferences, 7 million consent records and full residential PII — behind nothing but an open port.