Supply Chain Security

CVE-2026-45321: Anatomy of the TanStack npm and PyPI Supply Chain Worm

The Mini Shai-Hulud worm hit TanStack, Mistral AI, UiPath and 170+ npm and PyPI packages by hijacking a trusted release pipeline mid-run. Here is how the software supply chain attack actually worked, and what it changes.

Nayan Dey
Senior Security Engineer
7 min read

If you want to understand where software supply chain attacks are headed, stop reading the headlines about how many packages were hit and look at how this one got published. The TanStack compromise, tracked as CVE-2026-45321 and nicknamed "Mini Shai-Hulud," is not interesting because it touched 170-plus packages across npm and PyPI. It is interesting because the malicious versions were signed and shipped by TanStack's own legitimate release pipeline, using its real OIDC identity, after an attacker took over the runner mid-workflow. That detail matters more than the body count.

This was a two-wave campaign. According to TanStack's own postmortem and reporting from multiple firms, attackers staged malicious artifacts in late April 2026 and then executed the main wave in May 2026. The advisory tracked as CVE-2026-45321 has been scored in the critical range, which is the correct altitude for "credential theft plus self-propagation plus a destructive payload." Let me walk through what actually happened, because the mechanics are the lesson.

The CI/CD attack chain, step by step

The entry point was not a stolen npm token. It was GitHub Actions.

Per TanStack's postmortem, the attacker forked the TanStack/router repository under a renamed account to dodge casual detection, then opened a pull request that triggered a workflow using the pull_request_target event. That trigger is the load-bearing mistake in a lot of CI/CD setups: unlike pull_request, pull_request_target runs in the context of the base repository with access to its secrets, while still being influenced by code from the fork. The attacker used that foothold to poison the GitHub Actions cache, planting a malicious pnpm store.

The poison sat dormant. When legitimate maintainer pull requests were later merged and the release workflow ran, it restored the poisoned cache, executed attacker-controlled code, and pulled an OIDC token out of the runner process memory. From there the pipeline did exactly what it was designed to do: build, sign, and publish. Reporting indicates that within a window of only a few minutes, dozens of malicious artifacts went out across the @tanstack namespace alone.

Read that timeline again. Minutes, not hours. No credential was phished, no maintainer was compromised in the usual sense. The trusted identity was borrowed for the length of one workflow run.

Why "valid provenance" is the scary part

Here is the line from this incident that should change how you think about attestation. Per StepSecurity's analysis, this is among the first reported cases of a malicious npm package shipping with valid SLSA provenance.

We have spent the last few years telling teams that provenance and attestation are the answer to "did this artifact really come from where it claims." That advice is still correct, but this attack exposes its boundary. Provenance proves an artifact was built by a specific pipeline from specific source. It does not prove that pipeline was uninfected at build time. If you compromise the build environment instead of the signing key, you get a malicious artifact with a perfectly genuine signature and a clean provenance trail. Every downstream verifier that checks "is this signed by the expected workflow" says yes.

So provenance raises the cost of an attack, which is good. It does not by itself certify intent or integrity of the build. The defensive frontier moves up a layer, into the integrity of the CI/CD environment that produces the attestation in the first place.

The payload: harvest, then spread

Once a developer or a CI runner installed any affected version, the malicious code ran during npm lifecycle hooks. Based on the published analyses, it went after the obvious high-value secrets:

  • GitHub and npm tokens
  • AWS credentials, reportedly via the IMDSv2 metadata endpoint
  • GCP and Azure credentials
  • Kubernetes service account tokens
  • HashiCorp Vault tokens
  • General environment variables

This is the OAuth-token-theft and CI/CD-secrets playbook, and it is precisely what makes a build farm such a juicy target: the secrets sitting in a CI runner are usually broader and longer-lived than anything on a laptop.

The worm behavior is what earned the Shai-Hulud comparison. After harvesting, the payload reportedly enumerated the packages the victim had publish rights to, injected the same malicious dependency into them, bumped versions, and republished using the stolen tokens. Each infected developer and each infected runner becomes a new launch point. That is how a single poisoned cache becomes 170-plus packages across two ecosystems, spanning namespaces like @tanstack, @uipath, @squawk and @mistralai on npm, plus PyPI distributions including guardrails-ai and the mistralai client. Reporting also describes a destructive component capable of wiping developer home directories, so this was not purely a quiet credential grab.

The blast radius reached well-known names. OpenAI published a response noting that two employee devices were affected and that it pushed macOS updates in reaction. When a company with OpenAI's security maturity catches this on internal endpoints, the takeaway is not "they were careless." The takeaway is that transitive dependency compromise routes around posture you thought you controlled.

What this means for your dependency strategy

A few hard conclusions, stated plainly.

First, lockfiles and pinning matter, but only if your install path actually honors them and you are not auto-floating to new minor versions in CI. The window here was minutes; teams that pulled "latest" during that window were exposed, while teams pinned to known-good versions with integrity hashes were not.

Second, install-time and import-time code execution is still the soft underbelly of both ecosystems. npm lifecycle scripts and Python startup hooks run with whatever privileges your developer or runner has. Disabling lifecycle scripts by default, and only allowing them for an explicit allowlist, removes a large class of these payloads.

Third, treat CI/CD secrets as the crown jewels they are. Scope tokens tightly, prefer short-lived OIDC-issued credentials over long-lived static ones, and assume that any secret reachable from a build step can be exfiltrated by a build step. Audit your workflows for pull_request_target and confirm you are not running fork-influenced code with access to real secrets.

Fourth, build a verification habit, not just a signing habit. Checking that a package is signed is necessary and insufficient. You also want behavioral context: is this version a sudden mass-publish across an entire namespace in a six-minute window? That pattern is detectable, and it is the kind of signal that distinguishes a real release from a hijacked one.

How Safeguard Helps

Safeguard treats this exact failure mode as a first-class problem. Our AIBOM and ML-BOM give you a live inventory of every npm and PyPI component in your stack, so when a CVE like CVE-2026-45321 drops you can answer "are we exposed, and where" in minutes instead of days. Policy gates block the install or merge of compromised versions before they reach a runner, the vendor scorecard and provenance checks flag anomalies like a sudden namespace-wide mass-publish rather than just rubber-stamping a valid signature, and our Multi-Agent TAOR Deep Think engine runs verification in an orchestration layer above any single model so a compromised dependency or a noisy scanner does not become a missed finding. The model underneath is yours to choose; the reliability lives in the verification above it, and we measure ourselves on cost per verified finding, not raw alert volume.

If you want help auditing your dependency and CI/CD exposure to this campaign, reach out.

Sources: TanStack postmortem, Tenable, StepSecurity, Snyk, The Hacker News, SecurityWeek, NVD (CVE-2026-45321), and OpenAI's incident response note.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.