Can We Talk About This Now? Shai-Hulud Wave 2 Targeting npm

Khushal

Level 15
Thread author
Verified
Top Poster
Well-known
Apr 4, 2024
728
4,552
1,369
🚨 Shai-Hulud Wave 2 is here — and it’s far more destructive. 🚨
Back in September, Morphisec and Kaspersky warned that Wave 1 of this npm-targeting worm was just the beginning. ⚠️

Now Wave 2 has arrived — and the escalation is dramatic: 📈
🔹 25,000+ infected repositories
🔹 1,000 new infections every 30 minutes
🔹 Credential theft + destructive wiper behavior 💣
🔹 Docker-based privilege escalation to root 🔓
🔹 Advanced persistence through GitHub workflows 🧬

This isn’t just an open-source issue.
It’s a software supply chain crisis — and detection tools alone simply can’t keep up. ⏱️

If you work in software development, DevOps, security, or supply chain risk — this is a must-read. 📚
1770188582840.png

 
The Morphisec post is referring to a real, widely-reported “second wave” of the Shai-Hulud npm supply-chain worm, but the viral summary you quoted mixes “current” language with events that largely peaked in late 2025.

What’s confirmed (with concrete dates)
  • Wave 1: publicly disclosed mid-September 2025, focused on credential theft and worm-like propagation via compromised maintainer accounts and trojanized npm package versions. (Kaspersky covered the campaign and the “self-replicating” aspect in September 2025.)
  • Wave 2 / “Shai-Hulud 2.0”: activity reported starting around November 21–23, 2025, with peak reporting around November 24, 2025. Multiple write-ups cite Wiz’s observations about 25,000+ GitHub repositories exposing stolen secrets and bursts of ~1,000 new repos every 30 minutes.
  • Tradecraft changes in Wave 2 that are broadly reported: execution via npm “preinstall” (e.g., setup_bun.js / bun_environment.js), GitHub Actions workflow abuse and self-hosted runner persistence, and destructive behavior being observed/reported by multiple sources (not just Morphisec).

Important nuance about “25,000+ infected repositories”
In many reports, the “25,000+ repositories” figure refers to newly created/compromised GitHub repositories where stolen secrets were published/exposed (often auto-generated), not necessarily 25,000 legitimate upstream open-source projects having their source code backdoored. It’s still severe (credential leakage + automation), but it’s a different meaning than “25,000 popular projects shipped malware.”

Why “detection tools alone can’t keep up” is only partly true
Static scanners/allowlists can be bypassed when:
  • The payload runs in lifecycle scripts (preinstall/postinstall) and executes before later pipeline checks.
  • The attacker pivots into CI/CD (GitHub Actions) and persists via workflows/self-hosted runners.

But you can materially reduce risk with process and platform controls (not just “more AV”).

Practical mitigations (low-risk to higher-impact)
1) Immediate triage signals (repos/endpoints/build agents)
  • Search for: setup_bun.js, bun_environment.js, unexpected “preinstall” entries in package.json, and suspicious large/obfuscated JS blobs.
  • Audit .github/workflows/ for unexpected files (including discussion*.yaml / formatter*.yml patterns reported in write-ups).
  • Check GitHub org settings and runner inventory for unknown self-hosted runners (some reports mention “SHA1HULUD” naming).

2) Credential containment (high value)
  • Rotate npm tokens, GitHub tokens/PATs, and CI/CD secrets (and any cloud keys) that were present on developer machines or runners during installs/builds in the affected window.
  • Prefer short-lived credentials (OIDC where possible) over long-lived PATs and static cloud keys in CI.

3) Reduce blast radius in CI/CD
  • Revisit whether installs really need lifecycle scripts on CI runners; consider limiting script execution in CI where feasible (be careful: this can break legitimate builds).
  • Lock down self-hosted runners: restrict who can run workflows on them, isolate network access, and avoid exposing long-lived secrets to runner environments.

4) Supply-chain hygiene that helps against “next wave” too
  • Pin and review dependency updates (lockfiles, controlled update cadence).
  • Use provenance/signing where available, and enforce branch protection + review for workflow changes.
  • Continuously monitor leaked secrets (internally) and treat public GitHub exposure as an incident, not a “cleanup task.”

If you’re posting this to warn developers/DevOps teams, the most actionable framing is: “assume credential exposure + CI persistence risk,” then push rotation + workflow/runner audits, not just “scan your code.”

Sources
 
Technical Analysis & Remediation

Campaign Evolution & TTPs
The threat actor has shifted from simple credential theft (Wave 1, Sept 2025) to aggressive infrastructure hijacking (Wave 2/3).

Vector
Compromised npm tokens are used to publish patch versions (e.g., 18.0.2 -> 18.0.3) containing malicious preinstall hooks.

Execution Chain

Loader

The package.json triggers a script, typically named setup_bun.js, which downloads the Bun runtime (bypassing Node.js-specific detections).

Payload
Bun executes bun_environment.js, which serves as the primary infostealer and worm propagator.

Persistence
The malware registers the compromised machine as a self-hosted GitHub Action runner, often named SHA1HULUD.

Lateral Movement
It injects a workflow file (e.g., .github/workflows/discussion.yaml) that allows the attacker to execute arbitrary commands by creating GitHub Discussions.

Indicators of Compromise (IOCs)

File Artifacts


setup_bun.js

bun_environment.js

.github/workflows/discussion.yaml

c9nt3nts.json (Exfiltrated data artifact in Wave 3)

String Literals

SHA1HULUD (Runner Name)

Shai-Hulud: The Second Coming (Repository Description)

Network/Infra

Mass creation of repositories with "Shai-Hulud" in the name/description.

Outbound traffic to raw.githubusercontent.com fetching c0nt3nts.json (Wave 3 behavior).

Lifecycle & CVE Context

MITRE ATT&CK

T1195.001 (Compromise Software Dependencies)
T1574.006 (DLL Side-Loading [via Runtime])
T1552 (Unsecured Credentials).

Vulnerability Profile
While no single CVE defines the worm, it exploits weak identity posture (long-lived tokens) and unpinned dependencies.

Wave 3 Variance
Recent telemetry indicates the removal of the "dead man's switch" (which previously wiped data if tokens weren't found), making Wave 3 stealthier and more persistent.

Remediation - THE ENTERPRISE TRACK (SANS PICERL)

Phase 1: Identification & Containment

Hunt for Runners

Immediately query GitHub Organization settings for unauthorized self-hosted runners matching the pattern SHA1HULUD or created by service accounts in the last 90 days.

Dependency Audit
Scan package-lock.json files for the presence of setup_bun.js in execution scripts.

Block Execution
Use AppLocker/WDAC to block the execution of the bun binary if it is not a standard tool in your environment.

Phase 2: Eradication

Token Rotation (CRITICAL)

Rotate all secrets exposed to the build environment. This includes:

NPM Automation Tokens.

AWS/Azure/GCP Cloud Credentials (check ~/.aws/credentials).

GitHub Personal Access Tokens (PATs).

Sanitize Repos
Delete any workflows (.github/workflows/discussion.yaml) created by the malware.

Reimage Build Agents
Do not attempt to clean infected runners; reimage them entirely as the malware has root-level persistence capabilities.

Phase 3: Recovery

Pin Dependencies

Enforce npm ci (clean install) which respects lockfiles, preventing the silent installation of new, compromised patch versions.

Dependency Cooldown
Implement a policy (via Artifactory/Nexus) to block packages published within the last 72 hours.

Phase 4: Lessons Learned

OIDC Implementation

Transition from static long-lived keys to OpenID Connect (OIDC) for cloud authentication in CI/CD to eliminate the credential theft surface.

Remediation - THE HOME USER / DEVELOPER TRACK

Priority 1: Safety & Isolation

Disconnect

If you executed npm install on a public project recently and noticed a Bun installation or high CPU usage, disconnect the machine.

Scan
Run a dedicated secret scanner (like TruffleHog) locally to see what credentials might have been on disk and exposed.

Priority 2: Identity Hygiene

Reset Everything

Assume your local ~/.ssh/id_rsa, .npmrc, and environment variables are compromised. Revoke and regenerate these keys immediately.

Enable 2FA
Ensure Two-Factor Authentication is enforced on your npm and GitHub accounts to prevent attackers from using your identity to publish further malware.

Priority 3: Persistence Removal

Check Scheduled Tasks

Look for background processes keeping bun or node active when no development environment is running.

Hardening & References

Baseline

CIS Software Supply Chain Security Guide v1.0 (Section 3: Dependency Management).

Framework
NIST SSDF (SP 800-218) - PS.3.2: Verify the provenance of third-party software.

Tactical
Verify no unknown runners exist in Settings > Actions > Runners.

Sources

Morphisec Threat Report

Kaspersky (Wave 1 Analysis - Sept 2025)

Infrastructure & Impact Reports (Wave 2 - Nov 2025)

Vendor Response & Remediation
 
As a home user who barely installs a few things and just crosses fingers 🤞, what I take from all this is that Shai-Hulud isn’t just a “weird coder bug” anymore, it’s a reminder that our passwords and accounts are always in the crosshairs.For those of us who don’t touch npm or GitHub every day, the direct risk is low… but if the apps we use are cooked in infected kitchens, the dish still reaches us spoiled 🍲💀.So: two‑factor everywhere, keep updates rolling, and zero trust in “magic packages” that promise more than they should.Table‑side moral: even if you’re not the chef, when the kitchen fills with worms, sooner or later the diner notices 🐛🤮.