Breach analyses · 2026-05-11 · NPM Supply chain · Propagation worm

Mini Shai-Hulud: 170+ npm packages, valid provenance, scanners passed.

The May 11, 2026 npm supply-chain worm. The defining incident: a malicious package that carried valid SLSA provenance. Provenance verification and signature checks passed, so the versions published and were downloaded before behavioral scanners flagged them minutes later. The attack was state-divergent, not content-malicious.

Reference: Wiz Research · Snyk Disclosure

Facts of the incident

What we know.

First compromise

2026-05-11: 84 malicious versions across 42 @tanstack packages, pushed in a rapid burst through TanStack's own CI using npm OIDC trusted publishing. No publisher account or npm token was stolen.

Packages affected

170+ including TanStack, Mistral AI client, Guardrails AI

Provenance

VALID SLSA attestation. Same CI workflow signature. Existing scanners passed.

Payload behavior

A setup.mjs preinstall script plus a ~2.3 MB obfuscated router_init.js added to the tarball, wired in via a new optionalDependencies entry pointing at a raw GitHub commit. It harvests 100+ credential file paths (GitHub PATs, npm, AWS, HashiCorp Vault, Kubernetes and CI/CD tokens) and extracts an OIDC token from the Actions runner to mint a valid npm credential. Exfiltration ran over the Session network (filev2.getsession.org) and GitHub dead-drop repos.

Detection method

Automated behavioral scanners, not manual maintainer notice: Socket's AI Scanner flagged each compromised version within six minutes of publication, and StepSecurity's AI Package Analyst flagged them within minutes.

Detection time

~6 minutes to first automated detection; days to map the full campaign (April 29 to May 13, 2026).

Why existing tooling missed it

Provenance is necessary but not sufficient.

SLSA, Sigstore, npm provenance: these are real defenses against an attacker who lacks build-pipeline credentials. They prevent forged provenance.

Mini Shai-Hulud bypassed provenance by compromising the maintainer's build pipeline first. Once inside the legitimate pipeline, the attacker's publishes carry legitimate SLSA attestations. The signature is valid because the signing identity was stolen, not forged.

Point-in-time scanners ask: "does this package have known-bad signals right now?" The compromised packages had no known-bad signals at the moment of publish. The signals that mattered were relative to the package's own history, not absolute.

How SCG state-divergence detection would catch this at version 1

Six divergence signals, all from the worm's actual signature.

Preinstall script newly added

+30

Baseline: Absent or stable across prior versions

Compromise version: New setup.mjs preinstall script present in compromised version 1

Publish-rate burst anomaly

+35

Baseline: 1-4 publishes per month per package

Compromise version: 84 versions across 42 packages pushed in one rapid CI-driven burst

Outbound network egress to fresh domains

+25

Baseline: No network calls in prior versions

Compromise version: Exfil to the Session network (filev2.getsession.org) and typosquat domains (git-tanstack.com)

Cross-package hash collision

+50

Baseline: Independent payloads across packages

Compromise version: Same router_init.js payload hash appears across many @tanstack packages

OIDC token extraction

+40

Baseline: No runtime credential reads

Compromise version: Extracts an OIDC token from the Actions runner (process memory) to mint an npm credential

Dependency tree delta

+15

Baseline: ±0-2 deps per minor release

Compromise version: New deps added; some with their own divergence signals

SCG's divergence score sums weighted signals. Thresholds: <20 allow · 20-49 alert · 50-79 require HITL · ≥80 deny. Mini Shai-Hulud version 1 scored well over 100 on every compromised package. State-aware detection is designed to catch it on first publish, before signature databases have ever seen it, once SCG ships (public beta Q1 2027).

The four-layer defense

SCG is designed to ship as four composable surfaces.

Registry Mirror

One config line: registry=https://registry.synoi.systems

Silent default. Every npm install verified inline against the divergence index. Zero developer behavior change.

Supply Chain PR Bot

Install GitHub App once per org

Brand-visible PR comments on every package-lock.json diff. Shows divergence verdict per pinned (version, integrity) pair.

Lockfile Verifier

None - runs as CI step

Belt-and-braces for orgs that won't change registry. synoi-verify package-lock.json queries the OID Resolver.

Verified Publisher

Wrap publish in release script + HITL surface

Publisher-side gate. Stolen npm token alone can't ship - every publish requires out-of-band human approval via SMS / Slack / system tray.

Supply Chain Guard is in active development; public beta Q1 2027.

The Lockfile Verifier and PR Bot are first to ship - free tier, zero friction. Registry Mirror and Verified Publisher follow. A public OID Resolver at oid.synoi.systems will be the federation moat once deployed; it is not live yet.