The npm Worm That Broke SLSA: Reading Mini Shai-Hulud, TanStack, and the OpenAI Incident
On 11 May 2026, a self-spreading npm worm called Mini Shai-Hulud compromised 42 TanStack packages in six minutes, hit OpenAI's developer environment, and shipped malicious code with valid SLSA Build Level 3 attestations attached. V-Spot's reading of how the defence became the delivery vehicle, and what every team using npm should do about it.
On 11 May 2026, between 19:20 and 19:26 UTC, the TanStack family of npm packages was compromised by a self-spreading worm called Mini Shai-Hulud. Eighty-four malicious versions shipped across 42 TanStack packages in six minutes. The worm carries valid SLSA Build Level 3 attestations, the first npm supply chain attack to do so. OpenAI confirmed that two of its employee devices were affected.
The attack is attributed to TeamPCP, the DPRK-linked actor cluster we have been tracking across the V-Spot TeamPCP research series and covered in the Axios npm brief two months ago. The Mini Shai-Hulud wave has since spread to 169 npm and PyPI packages with a combined 518 million downloads, hit Mistral AI and Guardrails AI, and forced public disclosures from OpenAI, Trellix, and several smaller vendors. The full incident has been documented by TanStack themselves, Snyk, StepSecurity, The Hacker News, and the SLSA project itself, among others.
What makes this incident the most consequential supply chain attack of the year is not the package count or the OpenAI angle. It is that the malicious packages carry valid SLSA Build Level 3 attestations: the cryptographic certificates that were supposed to make exactly this kind of attack impossible. The defence did not fail. The defence was hijacked, and it correctly attested to the malicious build. This is V-Spot's reading of how that happened and what it means.
What happened on 11 May, in sequence
The TanStack compromise itself took six minutes. The work that made those six minutes possible took weeks, and it sat dormant in the project's CI configuration until the attacker chose to trigger it.
The first thing to know about Mini Shai-Hulud is that it is a worm. Once it compromises one package, it uses the credentials it steals (npm tokens, GitHub tokens, OIDC tokens, cloud secrets) to compromise the next set of packages on its own. The TanStack incident is one node in a campaign that started weeks earlier, and the campaign continues. The current wave has produced 373 malicious package-versions across 169 package names.
The second thing to know is that the worm targets the build pipeline, not the source code. The TanStack source repository on GitHub was never modified. No commit was pushed. No release was tagged. The malicious code was injected during the build, after the code was checked out, before the npm artefact was produced. A reviewer reading the repository would have seen nothing wrong. A bot checking the published package signature would have seen a valid signature. The harm sat in the gap between the source and the binary.
The third thing is that the package @tanstack/react-router alone is downloaded approximately 12.7 million times per week. The blast radius for a six-minute compromise of TanStack is meaningfully larger than the blast radius for most state-sponsored intrusions in the past decade.
The attack chain in three steps
The mechanism is technical, but the structure is simple. Three steps, each of which exploited a default behaviour in GitHub's CI system.
Step one: get attacker code running inside the target's own CI environment.
GitHub provides a workflow trigger called pull_request_target. The trigger was designed so that maintainers can run CI on a fork's pull request with the maintainer's secrets attached, which is useful for legitimate integration testing. Crucially, pull_request_target runs against the workflow definition on the *target* branch, but it checks out the *attacker's* fork code by default. If the workflow does anything with the checked-out code (running a script, installing dependencies, executing tests) the attacker's code runs inside the target's CI environment with the target's permissions.
The TanStack workflow had a pull_request_target step that did exactly this. The attacker opened a pull request from a fork they controlled. The TanStack CI pipeline picked up the workflow definition from the main branch, but checked out the attacker's code, then ran scripts against it. The attacker's code began executing inside TanStack's CI runner with TanStack's secrets in scope.
Step two: poison the build cache so the malicious payload survives the workflow run.
The attacker's code did not try to publish malicious packages from inside the pull request workflow (that would have triggered alarms). Instead, it wrote a malicious payload into the GitHub Actions cache. GitHub Actions caches are scoped per repository, not per workflow run. A cache written by the pull request workflow is available to all subsequent workflow runs against that repository, including release workflows that maintainers trigger.
The poisoned cache contained a modified pnpm store: the JavaScript dependency manager's local cache of every dependency the project uses. When subsequent builds drew from this cache, they used the attacker's modified versions of the project's own dependencies instead of the real ones.
Step three: wait for a maintainer to ship a release, then ride the legitimate release pipeline.
Days later, a TanStack maintainer merged a routine pull request to main and triggered a release. The release workflow ran in clean state, restored the cache (which is the cache the attacker had poisoned), built the packages using the poisoned pnpm store, and published the resulting artefacts to npm. The release workflow also extracted an OIDC token from the GitHub Actions runner's process memory and used that token to obtain a SLSA Build Level 3 attestation for the published artefacts. The Sigstore infrastructure verified the build process and signed the attestation, because from Sigstore's point of view, the build had run correctly. It had. It had built malicious code.
The result: 84 packages published to npm in six minutes, each cryptographically attested as built by a trusted source, because they were.
Why SLSA did not catch this
SLSA Build Level 3 attestations promise specific things: the build was hermetic, the build process was tamper-resistant during execution, the build provenance was generated by a hardened service, and the attestation is cryptographically tied to the actual artefact. All four were true for the TanStack malicious packages. The attestations were valid. The defence did its job.
The problem is what SLSA does not promise. SLSA verifies the integrity of a build, not the integrity of the source the build acted on. If the source was the right source (and in TanStack's case, the official TanStack repository on the official branch was the source), but the build environment had been pre-compromised in a way that altered the dependencies used during the build, SLSA has no mechanism to detect that. The build itself was a faithful build of whatever was in the runner at the time. What was in the runner was poisoned.
The SLSA project published an explicit response to the incident. Their summary is worth reading directly: SLSA was designed to defend against attackers who control or compromise a source repository, not against attackers who can run arbitrary code inside the build infrastructure itself. Mini Shai-Hulud demonstrates that the latter threat is real, exploitable, and currently undefended at the protocol level.
For the rest of the npm ecosystem, this collapses the threat model. The signal "this package has a valid SLSA Build Level 3 attestation" is now ambiguous in a way it was not on 10 May. It means the build ran correctly. It does not mean the build was clean.
The OpenAI angle, and what it tells us about agent supply chains
OpenAI publicly disclosed that two of their employee devices were compromised through Mini Shai-Hulud. The affected products were the macOS builds of ChatGPT Desktop, Codex App, Codex CLI, and Atlas. OpenAI's investigation concluded that no customer data, no production systems, and no core intellectual property were compromised. They forced an update of the affected macOS products.
The OpenAI incident is consequential beyond the specifics. It is the first major commercial AI vendor to publicly disclose a supply chain compromise of their developer environment, and the compromise rode an npm package they consumed transitively. Their AI products did not have a vulnerability in the AI sense. The vulnerability lived two or three transitive dependencies deep in a frontend tooling chain that their developer machines installed automatically when they ran npm install.
This pattern, the agent supply chain, was the first of the seven new failure modes Microsoft added to their agentic-AI taxonomy update earlier this month. Microsoft's red team called supply chain compromise the failure mode they encountered most frequently in real engagements. The TanStack incident is the field evidence for that finding, two weeks after Microsoft's publication.
If you are shipping AI agents into regulated industries, the threat model is no longer "what if our model is wrong" or "what if our prompts are manipulated." It includes "what if an npm package three layers deep in our developer environment was backdoored by a worm in late May."
V-Spot's reading
Three things this incident says about the state of supply chain security in mid-2026.
The dominant defensive posture is now structurally insufficient. The industry consensus before Mini Shai-Hulud was: pin your dependencies, audit your maintainers, and demand SLSA attestations on the packages you consume. Mini Shai-Hulud was downloaded by teams that did all three. The pinning was correct. The maintainer was real. The attestation was valid. The package was malicious. The defensive recommendations need to extend to the build environment itself, not just the artefacts the build produces.
Build-environment compromise is the next major attack surface. Mini Shai-Hulud is the proof of concept. The pattern (compromise the runner, poison the cache, ride the legitimate release pipeline to ship attested malicious packages) is portable to every CI system that supports forked-PR workflows with target-side secrets. GitHub is not unique. GitLab's analogous primitive, Jenkins-with-credentials, CircleCI's context system, all share the same general shape. The next six months of public incidents will likely include attacks on at least one other major CI platform using the same pattern.
The CI runner now needs the same security posture as production. Most teams treat CI runners as ephemeral, low-value compute. They run with broad permissions, broad network access, and minimal logging. Mini Shai-Hulud should change that. A CI runner with access to npm publish credentials, OIDC issuance, and the production deployment pipeline has more sensitive access than most production servers. It needs to be treated accordingly.
What to do this week
Practical and ordered by impact-per-hour-of-effort.
Inventory which repositories your team owns that use `pull_request_target` triggers in their workflows. This is the primitive Mini Shai-Hulud abused. Not every use of pull_request_target is dangerous, but every use needs justification. If you find one with no documented reason, remove it.
For any repository that needs `pull_request_target`, restrict the workflow's secret access. GitHub provides per-workflow permissions and per-environment secrets. The defence is to ensure that the workflow run triggered by a fork PR cannot read credentials it does not strictly need. Most legitimate uses of pull_request_target need none.
Audit your CI cache strategy. GitHub Actions caches and analogous primitives in other platforms are scoped per repository. A cache poisoned by one workflow is available to all others. Where possible, isolate cache scopes per branch or per workflow, and avoid cache restoration in release workflows that publish to a registry.
Treat CI runner memory as sensitive. The OIDC token extraction step of Mini Shai-Hulud worked because the runner did not protect the token in memory. Self-hosted runners can be hardened to reduce the readable token surface. GitHub-hosted runners cannot, which is one argument for self-hosting any runner that has access to publish credentials or production deployment.
Pin dependencies by content hash, not version. A pinned ^1.4.2 does not help if the published 1.4.2 artefact gets republished with the same version by an attacker. Pinning by SHA of the tarball content does. npm supports this via lockfile integrity hashes. The work is operational, not technical.
Subscribe to the threat-intel feeds that track this category. StepSecurity, Socket, Snyk, GitHub Advisory Database, and the SLSA project's blog all covered Mini Shai-Hulud in real time. The rate of new disclosures in this space is accelerating, and the cost of subscribing is low.
Run the V-Spot four-question dependency review against your top-50 most-installed packages. The framework we published with the Axios brief holds against Mini Shai-Hulud: who can publish, how is publishing authenticated, what runs at install time, what runs at build time. Mini Shai-Hulud surfaces a fifth question worth adding: what runs in the CI environment the build executes inside.
What comes next
Two forward predictions V-Spot's research division will stand behind.
Within six months, a second major CI platform will be hit by a Mini-Shai-Hulud-class attack. The technique is now public and well-documented. The same pattern works against any CI system that supports forked PR workflows running with target secrets. GitLab and self-hosted Jenkins are the obvious next targets. Probability is high enough that organisations operating those platforms should be threat-modelling for it now.
Within twelve months, the industry consensus around SLSA shifts from "achieve Level 3 and you are safe" to "Level 3 is necessary but not sufficient." A new layer of defence (build-environment attestation, runner-image attestation, or something equivalent) becomes a topic of active proposal. Whether it lands as a SLSA Level 4 or a separate standard is open. That it gets proposed is not.
Closing
The TanStack compromise was six minutes of damage built on weeks of patient pre-positioning by a state-sponsored actor we have been tracking on this blog for three months. The malicious packages it produced are technically indistinguishable from legitimate ones because they ran through the same legitimate build pipeline, with the same legitimate signing infrastructure, that produced TanStack's real releases. This is the supply chain threat model V-Spot has been writing toward since the Axios brief: a build pipeline that is itself a compromise vector, with attestation systems that confirm rather than detect the compromise.
The defensive answer is layered, operational, and not glamorous: audit your CI triggers, scope your secrets tightly, isolate your caches, harden your runners, pin by content hash. None of it is new advice. All of it now matters more than it did on 10 May.
If you are mid-response on Mini Shai-Hulud, or rebuilding your supply chain posture in light of it, V-Spot's research division and offensive security team can help.
---
Sources:
- Mini Shai-Hulud Is Back: A Self-Spreading Supply Chain Attack Compromises TanStack npm Packages, StepSecurity
- TanStack npm Packages Hit by Mini Shai-Hulud, Snyk
- Mini Shai-Hulud Worm Compromises TanStack, Mistral AI, Guardrails AI and More Packages, The Hacker News
- Mini Shai-Hulud: Where SLSA's Boundaries Fall, SLSA Project
- Our response to the TanStack npm supply chain attack, OpenAI
- TanStack Supply Chain Attack Hits Two OpenAI Employee Devices, Forces macOS Updates, The Hacker News
- TanStack and 160+ npm/PyPI Packages Compromised in Supply Chain Worm Attack, Orca Security
- Mini Shai-Hulud: TanStack, OpenAI, and the npm Supply Chain Trap, OPSWAT
Frequently asked questions
- What is Mini Shai-Hulud?
- Mini Shai-Hulud is a self-spreading supply chain worm that targets the npm and PyPI package registries. Attributed by StepSecurity to the threat actor cluster known as TeamPCP, it steals developer and cloud credentials and uses them to publish poisoned versions of additional packages, which then propagate further. The campaign first surfaced in late 2025 and reached its largest known wave on 11 May 2026 with the TanStack compromise.
- What was the TanStack compromise on 11 May 2026?
- On 11 May 2026, between 19:20 and 19:26 UTC, the worm shipped 84 malicious package versions across 42 TanStack npm packages in a six-minute window. The compromise abused a GitHub Actions pull_request_target workflow to poison the build cache, then extracted OIDC tokens directly from the runner's process memory and used them to publish via the legitimate release pipeline.
- Why are the malicious packages described as the first ever to carry valid SLSA attestations?
- SLSA Build Level 3 attestations are cryptographic certificates that prove a package was produced by a specific build pipeline. Mini Shai-Hulud is the first documented case of malicious npm packages carrying valid SLSA Build Level 3 attestations, because the worm rode the legitimate build pipeline through Sigstore's verification rather than bypassing it. SLSA verified that the build pipeline ran. It does not verify whether the build environment itself was compromised.
- What was the impact on OpenAI?
- OpenAI publicly disclosed that two employee devices were compromised through the campaign. As a precaution they rotated the code-signing certificates for the macOS builds of ChatGPT Desktop, Codex App, Codex CLI, and Atlas, and required users to update by 12 June 2026. They reported no evidence that customer data or production systems were affected.
- How wide is the Mini Shai-Hulud spread?
- Beyond TanStack, the worm has propagated to at least 169 packages across the npm and PyPI registries, with a combined download base in the hundreds of millions. Affected projects include Mistral AI, Guardrails AI, and SAP-related npm packages. The cluster has been attributed to TeamPCP, the same actor cluster behind the Axios npm compromise in March 2026.
- What should engineering teams do in response?
- Audit GitHub Actions workflows for pull_request_target triggers that allow secret access to forks; restrict runner cache write permissions; pin third-party Actions by full commit SHA; rotate any npm or registry tokens that were issued before 11 May 2026; and treat the validity of provenance attestations as evidence of pipeline behaviour, not of code intent.