A Supply-Chain Attack That Keeps Evolving

The Shai-Hulud campaign has become one of the more instructive supply-chain threats targeting the JavaScript ecosystem. What began as a relatively straightforward abuse of compromised maintainer accounts has since grown into a multi-wave effort that appears engineered specifically to outpace defenders.

The first wave injected malicious post-install scripts into packages, harvesting secrets and replicating itself across dependency chains from a single foothold. The second wave — Shai-Hulud 2.0 — added self-propagation via compromised credentials that enabled cross-victim credential exposure, along with destructive capabilities. It also changed behavior when running in CI environments, attempted privilege escalation against specific build agents, and used a multi-stage payload that was notably harder to detect. The shortened interval between variants points to an adversary actively studying community responses and iterating around them.

Across the waves, a few defining patterns stand out:

  • Credential-adjacent compromise: Footholds begin with stolen credentials or OAuth tokens, then expand through collection of npm tokens, CI tokens and cloud credentials — an approach that reuses access across organizations and keeps future waves viable without a single point of failure.
  • Install-time execution with obfuscation: Malicious lifecycle scripts embed in packages and only activate at runtime, often conditional on environment checks or organization scopes, with exfiltration tailored to the running environment.
  • Trust abused in familiar names: The campaign targeted trusted packages and republished infected versions under existing package names. Shai-Hulud 2.0 even matched version numbers so tainted packages looked like routine maintenance updates.
  • Iteration around defenses: Short turnaround between variants with deliberate changes to bypass previous mitigations indicates a campaign engineered for durable access and scalable spread, not opportunistic one-offs.
  • Publication pipeline blind spots: Differences between source and published artifacts, lifecycle scripts and build-time transformations leave gaps where injected code can slip through without artifact validation or staged approvals.

The lesson for defenders is to harden publication workflows and credential flows rather than tune mitigations to a single variant.

What npm Is Building Next

Work on the npm security roadmap is being accelerated to address this threat landscape. Over the next two quarters, the focus is on three capabilities:

  • Bulk OIDC onboarding: Tooling to help organizations migrate hundreds of packages to trusted publishing without per-package friction.
  • Expanded OIDC provider support: Covering CI providers beyond the current GitHub Actions and GitLab integrations.
  • Staged publishing: A model that gives maintainers a review window before a package goes live, with MFA-verified approval from owners — a safeguard for catching unintended changes before downstream users see them.

Practical Guidance for Users and Maintainers

The fundamental attack vector remains the same: malware added to a package runs at install time, compromising any developer who installs it. The malware scavenges the local machine for tokens, which can fuel propagation — and because packages pull in many dependencies, one poisoned package can reach far. Notably, the attackers hoard some tokens rather than spending them all at once, enabling new campaigns weeks or months later.

For Everyone

  • Enable phishing-resistant MFA across accounts, including package manager registries and any account that could enable account takeover — email and social media included.
  • Set expiration dates on tokens so they rotate on schedule. Organizations can enforce a maximum lifetime policy for personal access tokens.
  • Audit and revoke unused GitHub and OAuth app authorizations.
  • Do development work in a sandbox — GitHub Codespaces, a VM or a container — to limit what malware can reach if it does execute.

For Maintainers

  • Use branch protection so malicious pushes can't land on the main branch, even with a valid token.
  • Prefer trusted publishing over standing tokens. The option exists beyond npm — PyPI, RubyGems and NuGet all support it.
  • Pin CI dependencies, enable code scanning and act on its alerts.
  • Validate what ships: monitor artifacts and check published tarballs against source using SRI or artifact build attestations.

These are preventative measures. If you believe you have been targeted and need help securing a GitHub or npm account, contact GitHub Support directly.