An independent re-analysis by Goldberg Security Research of a publicly-reported campaign, drawn from open reporting (CISA, Unit 42, Wiz, Microsoft — see references). Not original discovery.

Why it mattered

Shai-Hulud was the first successful self-propagating worm in the npm ecosystem. Earlier supply-chain incidents were one-shot package compromises; Shai-Hulud automated the spread, turning each victim maintainer into a launch point for the next — the closest the JavaScript ecosystem has come to a true worm.

Initial compromise

The entry point was a credential-phishing campaign spoofing npm and prompting maintainers to "update" their MFA settings — harvesting their npm authentication token in the process.

Self-replication

This is the core of the threat, and it is elegant in the worst way:

  1. Using a stolen token, the payload authenticates to the npm registry as the compromised maintainer.
  2. It enumerates that maintainer's other packages.
  3. It injects its malicious code into each, bumps the version, and re-publishes them.
  4. Every developer who installs an infected package becomes a new spreader — exponential growth, no operator intervention.

Payload

The malicious postinstall script runs on install and harvests secrets aggressively:

  • Runs TruffleHog (a legitimate secret scanner, repurposed) to find credentials on the host.
  • Harvests environment variables and cloud keys exposed via the instance metadata service (IMDS).
  • Exfiltrates findings to attacker-created public GitHub repositories named "Shai-Hulud" — a distinctive, public IOC.

Scale & variants

The first wave hit 500+ packages including the widely-used @ctrl/tinycolor. The November 2025 Shai-Hulud 2.0 backdoored ~796 unique packages totalling over 20 million weekly downloads, and a 2026 "Mini Shai-Hulud" resurgence extended into PyPI. The recurrence underlines that npm token hygiene and lifecycle-script trust remain systemic weak points.

Detection & prevention

  • Hunt for public GitHub repos named Shai-Hulud under your org's developers; review npm publish logs for unexpected version bumps.
  • Install with --ignore-scripts in CI; gate lifecycle scripts.
  • Use short-lived, scoped npm tokens with mandatory 2FA on publish; rotate on any suspicion.
  • Restrict IMDS access from build agents (IMDSv2/hop-limit) so a postinstall can't grab cloud creds.
  • Pin lockfiles; alert on new transitive versions of high-fan-out packages.

Remediation

  • Rotate every secret reachable from affected developer or CI hosts (npm, cloud, Git, SSH).
  • Roll back to known-good package versions; purge caches and rebuild agents from clean images.
  • Audit and revoke npm tokens; re-enable enforced 2FA for publishing.

References