Shai-Hulud Worm Attack: How the npm Ecosystem Got Hit and What Builders Should Do

I'm a full-stack engineer from Kerala. Helping startups turn their ideas into digital realities.I specialize in designing and building modern web solutions.
1. Setting the Stage: A New Breed of Supply Chain Attack
The Shai-Hulud campaign represents a critical evolution in supply chain threats, moving beyond isolated package compromise to a self-propagating contagion targeting the core of modern development workflows. This attack is not just another malicious package; it is a sophisticated, worm-like threat that weaponizes trusted developer tools and infrastructure to spread, steal credentials, and establish persistent backdoors.
The strategic importance of this topic cannot be overstated. The global annual cost of software supply chain attacks is projected to reach an alarming 60 billion in 2025 and is forecast to climb to 138 billion by 2031. For any engineering lead, developer, or security professional, understanding this attack is not an academic exercise—it is a critical lesson in modern defensive engineering and a case study in the advanced threats targeting our development ecosystems.
2. Anatomy of the Worm: How Shai-Hulud Works
Shai-Hulud's effectiveness stems from a sophisticated, multi-stage design that evades casual inspection and maximizes impact. By chaining together legitimate tools, obfuscated payloads, and clever persistence mechanisms, the worm methodically compromises a system, harvests its secrets, and uses them to infect others.
Initial Infection: The
preinstallHookThe attack begins when a developer installs a compromised npm package. The malware uses a
preinstallscript in thepackage.jsonfile to execute a loader script namedsetup_bun.js.The choice of the
preinstallhook is significant. It ensures the malware runs before the package installation process completes, meaning the payload can execute even if the overall package installation fails for other reasons.
Evasion via Legitimate Tooling: The Bun Runtime
The
setup_bun.jsloader cleverly checks for the presence of the legitimate Bun JavaScript runtime. If Bun is not found, the script automatically downloads and installs it from the official source.This "Living Off the Land" technique is highly effective for evasion. By installing and using a legitimate, high-performance developer tool, the malware's initial activity appears routine and is less likely to be flagged by security tools.
Once Bun is installed or located, it is used to execute the primary payload: a heavily obfuscated 10MB file named
bun_environment.js, which is launched as a detached background process.
Systematic Credential Harvesting
The malware's primary objective is to aggressively harvest developer credentials. It systematically scans the compromised environment for npm tokens, GitHub Personal Access Tokens (PATs), and cloud keys for AWS, GCP, and Azure.
Its methods went beyond scanning local files, as it could also directly query cloud-native services like AWS Secrets Manager and Azure Key Vault to extract high-value secrets. The worm’s sophistication is further evident in its use of an embedded version of the legitimate open-source tool TruffleHog to scan the user's entire home directory for secrets.
Data Exfiltration and Propagation Network
Stolen GitHub tokens are immediately used to create new public GitHub repositories. These repositories serve as drop points for exfiltrated data and are identifiable by the description "Sha1-Hulud: The Second Coming."
All stolen data—including credentials, system information, and environment variables—is uploaded to these repositories in JSON files, typically double Base64-encoded to provide a basic layer of obfuscation, with some instances observed using triple encoding.
The worm then uses stolen npm tokens to propagate. It automatically downloads all other packages maintained by the victim, injects the malicious loader (
setup_bun.js), increments the package version, and republishes the newly infected packages to the npm registry, spreading the infection to downstream users.
The worm's self-given name, "The Second Coming," aptly signals its significant evolution from a previous, less advanced iteration.
Brrrrrrrrrrrrrrz. Attention span dying? Fine — here’s the video. But the real fun is below.
3. "The Second Coming": An Evolutionary Leap
Security researchers refer to this campaign as "The Second Coming" because it is a significantly evolved version of a prior attack, Shai-Hulud V1, which was first observed in September 2025. The name originates from the description the malware itself leaves in the exfiltration repositories it creates. This new variant demonstrates a clear learning curve, with threat actors refining their tactics to create a far more resilient, stealthy, and dangerous threat.
The table below highlights the key tactical evolutions from V1 to V2.
| Capability | Shai-Hulud V1 (September 2025) | Shai-Hulud V2 (November 2025) |
| Execution Hook | post-install (runs after installation) | preinstall (runs before, even if install fails) |
| Runtime | Node.js | Bun (lightweight, stealthier execution) |
| Exfiltration Method | External webhook endpoint (easily blocked) | Public GitHub repositories (blends with normal traffic) |
| Persistence | None | Self-hosted GitHub Actions runners |
| Credential Sharing | None | Cross-victim token recycling (botnet-like network) |
| Failsafe | None | Destructive "dead man's switch" wiper payload |
| Scale | ~200 packages compromised | 700+ packages, 27,000+ exfiltration repositories |
This evolution proves the threat actor's ability to learn from operational limitations and adapt their methods, making V2 a far more formidable supply chain threat.
4. The Origin Story: Who, Why, and How?
The Shai-Hulud V2 campaign was first detected around November 24, 2025, when security monitoring systems identified abnormal publication activity and malicious code commits in several widely used npm packages.
As of this writing, no confirmed attribution has been publicly disclosed regarding the threat actors. The significant tactical improvements over the V1 attack suggest two possibilities: either the original actor significantly refined their methods, or a new, more sophisticated group adopted and improved upon the established attack model.
The motivation behind the campaign appears to be the systematic, large-scale harvesting of high-value developer credentials. The goal was not just to compromise individual packages but to use stolen tokens to propagate the worm and gain access to valuable corporate cloud infrastructure, turning a developer workstation compromise into a full-scale organizational breach.
5. Assessing the Scale and Impact
The worm's automated, self-propagating design gave it a massive blast radius, allowing it to spread rapidly across the npm ecosystem. Within a short period, the campaign achieved a staggering scale.
Infected Packages: Over 700 distinct npm packages were compromised and republished with the malicious payload.
Malicious Repositories: More than 27,000 malicious public GitHub repositories were created to exfiltrate stolen data.
Exposed Secrets: Approximately 14,000 unique secrets were exposed across 487 different organizations.
The attack impacted several well-known and trusted organizations by compromising their official packages. Notable affected ecosystems include packages maintained by:
Zapier
ENS Domains
PostHog
Postman
However, it is the attack's technical design, not just its scale, that makes it a compelling and cautionary case study for every engineering team.
6. An Engineer's Curiosity: Why Shai-Hulud is Both Terrifying and Fascinating
While the Shai-Hulud worm is a severe threat, its technical architecture contains clever and novel mechanisms that are intellectually fascinating to deconstruct. From an engineering perspective, the malware demonstrates a deep understanding of modern DevOps tooling and exploits it in ways that challenge conventional security assumptions.
Elegant Evasion: The decision to use a legitimate, high-performance runtime like Bun was a masterstroke of evasion. This was a strategic choice to exploit the blind spots in security ecosystems that are overly optimized for Node.js. By using a less common but increasingly popular runtime, the initial infection activity appears as a routine developer tool setup, evading detection from tooling tuned only for standard Node.js behavior.
Novel Command and Control (C2) Channel: The persistence mechanism is particularly sophisticated. The malware installs a self-hosted GitHub Actions runner named
SHA1HULUDon the compromised machine. It then adds a malicious workflow file (discussion.yaml) to the exfiltration repository. This workflow was intentionally designed with a command injection point (run: echo ${{ github.event.discussion.body }}) that executes the content of any new GitHub Discussion post directly on the self-hosted runner. This effectively weaponized a legitimate collaboration feature, turning it into a stealthy, persistent C2 channel that bypasses traditional network firewalls.Resilient Botnet-like Network: The worm's design includes "cross-victim credential recycling." If the malware on a newly compromised machine failed to find a usable GitHub token locally, it would query GitHub's public search API for other repositories matching the "Sha1-Hulud: The Second Coming" marker. It would then attempt to download and parse the
contents.jsonfile from another victim's repository to retrieve and reuse their stolen token, making the entire attack network resilient against individual clean-up efforts.The "Dead Man's Switch" Paradox: The failsafe mechanism is its most terrifying feature. It's a strategic, anti-forensics tactic designed to protect the malware's infrastructure by weaponizing standard incident response. If the malware loses connectivity to both GitHub and npm simultaneously—a likely outcome of a mass takedown—it triggers a destructive payload. On Linux/macOS, it uses
shredto securely wipe files in the user's home directory; on Windows, it usesdelandcipher. This creates a "remediation paradox" where security teams must choose between immediate takedown (risking irreversible data loss) and careful containment (risking prolonged exposure while preserving forensic evidence).
These advanced tactics force a fundamental shift in how engineers must think about security risks within their daily development and CI/CD environments.
7. Who is at Risk? Developers and Organizations in the Crosshairs
The Shai-Hulud worm does not discriminate, posing distinct but overlapping risks to both organizations and the individual developers who work for them. Its design ensures that a compromise at either level can quickly escalate.
Organizations Under Threat
For organizations, the risks are systemic. A single infected developer machine can lead to the compromise of critical CI/CD pipelines, the poisoning of internal package repositories, and the theft of high-value cloud credentials. The exfiltration of AWS, GCP, or Azure keys grants attackers direct access to corporate infrastructure, enabling data theft, resource abuse, or further lateral movement within the company's cloud environment.
Individual Developers at Risk
Individual developers are on the front lines. The worm directly targets their local machines, stealing any personal cloud API keys, npm tokens, or GitHub PATs stored in their environment. This can lead to the compromise of personal npm packages, side projects, or any other resources tied to their stolen credentials, effectively turning their digital identity into a launchpad for the worm's propagation.
8. Proactive Defense: Hardening Your Development Environment
Preventing an attack like Shai-Hulud requires a strategic shift from reactive scanning to proactive governance and the enforcement of strict security policies across the entire development lifecycle. The following foundational controls can dramatically reduce the attack surface.
Enforce Strict Lockfile and Installation Integrity Mandate the use of
npm ciinstead ofnpm installin all CI/CD pipelines and automated builds. This ensures that installations strictly adhere to the versions specified in thepackage-lock.jsonfile, preventing the package manager from installing a newer, potentially malicious version that could be introduced via dependency confusion.Mitigate Malicious Lifecycle Scripts Mandate the use of
--ignore-scriptsby default for all manual installations, or enforce this globally in project.npmrcfiles by settingignore-scripts=true. This directly neutralizes the initial infection vector used by Shai-Hulud, which relied on thepreinstallhook to executesetup_bun.js.Implement Artifact Governance Organizations must control the flow of external dependencies. Route all package installation traffic through a private, curated internal registry or proxy. This allows security teams to vet, scan, and approve packages and their specific versions before they are made available to developers, creating a critical security gate that blocks the worm's automated propagation attempts.
Harden Identity and Access Management Since credential theft is the core of this attack, robust identity practices are non-negotiable. Enforce phishing-resistant Multi-Factor Authentication (MFA) on all developer accounts, especially for npm and GitHub, to counter the primary objective of the malware.
Apply the Principle of Least Privilege Use narrowly scoped, short-lived tokens for all CI/CD processes and automated tasks. A token should only have the permissions necessary to perform its specific job and should expire quickly. This minimizes the blast radius if a token is stolen, directly countering the worm's ability to use a single high-privilege token to propagate itself and establish persistence via a GitHub Actions runner.
While no single defense is perfect, implementing these controls as a baseline dramatically hardens the development environment against this class of supply chain attack.
9. Incident Response: A Checklist for a Confirmed Infection
Responding to a Shai-Hulud infection requires a precise, ordered checklist. The "dead man's switch" feature means that the order of operations is non-negotiable to avoid triggering the destructive payload.
Detection Use the
shai-hulud-detector.shscript provided in the JFrog security guide to scan local directories. Hunt for key Indicators of Compromise (IoCs), such as the presence of files namedsetup_bun.jsandbun_environment.jsin yournode_modulesdirectories or the creation of unexpected public GitHub repositories with the description "Sha1-Hulud: The Second Coming."Containment (The Dead Man's Switch Protocol)
Immediately navigate to the malicious repository and change its visibility from Public to Private. This action contains the data leak while keeping the worm's connection to GitHub active, thereby preventing the destructive failsafe from activating.
Eradication (Neutralize the Backdoor First)
Find and immediately disable or remove any self-hosted GitHub Actions runner named
SHA1HULUD. This can be done in your repository or organization's settings underActions > Runners. After neutralizing the runner, remove the malicious packages from your project by deleting dependency artifacts (rm -rf node_modules) and clearing the npm cache (npm cache clean --force).Recovery and Credential Rotation Once the persistence mechanism is confirmed to be removed, conduct a complete rotation of ALL exposed credentials. This includes all npm tokens, GitHub PATs, and any cloud service keys (AWS, GCP, Azure) identified in the exfiltrated files.
Post-Incident Audit Thoroughly audit cloud and source control access logs for any unauthorized activity that occurred after the compromise. Review and revoke any unrecognized third-party OAuth applications that have been linked to developer GitHub accounts.
Executing these steps in the correct order is essential to successfully remediating the infection without causing additional, and potentially irreversible, damage.
10. Long-Term Engineering Hygiene for a Resilient Supply Chain
The core lesson from Shai-Hulud is that supply chain security is not just about scanning packages; it is about applying a Zero Trust model to the entire developer toolchain. The weaponization of trusted infrastructure—from package managers and runtimes to CI/CD platforms and repository features like GitHub Discussions—demands a paradigm shift. True resilience is not a one-time fix but an ongoing practice of engineering hygiene.
Adopt a Zero Trust Mentality: Treat every component, user, and system as potentially compromised. Require strict verification for every access request, assume no implicit trust, and enforce the principle of least privilege everywhere.
Implement Curation and Immaturity Policies: Use artifact repositories like JFrog Artifactory to automatically block or quarantine newly published package versions for a set period. This "cooldown" allows the security community time to discover and flag malicious updates before they enter your environment.
Conduct Regular Dependency Audits: The attack surface of a project is proportional to its number of dependencies. Routinely review, audit, and remove unused or outdated packages to minimize exposure and simplify maintenance.
Integrate Continuous Security Monitoring: Automate security from the start. Use Software Composition Analysis (SCA) tools and malware scanning directly within CI/CD pipelines to detect threats early, provide immediate feedback to developers, and prevent compromised code from ever reaching production.



