Mini Shai-Hulud: How the TanStack npm Attack Spread to PyPI and Why Your CI/CD Is the New Attack Surface
A self-replicating worm compromised 172 open source packages across npm and PyPI in 48 hours, including TanStack, Mistral AI, and Guardrails AI. Here is how it worked, how it crossed registries, and what engineering teams need to do right now.
On May 11, 2026, a threat actor group known as TeamPCP executed one of the most technically sophisticated open source supply chain attacks ever documented. In under 48 hours, their worm, dubbed "Mini Shai-Hulud," spread across 172 packages totaling over 403 malicious published versions across both npm and PyPI. The targets included the entire TanStack router ecosystem, Mistral AI's Python and JavaScript SDKs, UiPath's automation packages, OpenSearch, and Guardrails AI.
The attack has been assigned CVE-2026-45321 with a CVSS score of 9.6, which puts it firmly in critical territory. Combined weekly downloads across the affected packages exceed 518 million. If you run Node or Python in production, your dependency tree deserves a close look.
Here is what happened technically, why it crossed from npm into PyPI, and what your team should do today.
What Is Mini Shai-Hulud
The "Shai-Hulud" naming comes from earlier TeamPCP campaigns documented in late 2025. The "Mini" designation refers to a refined, more surgical variant of the original worm, but the core self-propagation mechanism remains intact. What makes this variant historically notable is a first for the npm ecosystem: it shipped malicious packages carrying valid SLSA Build Level 3 provenance attestations. In other words, the malware passed the same integrity verification that organizations treat as a guarantee of trustworthy origin.
The Attack Chain: Three Steps to Full Compromise
The TanStack compromise was reconstructed in the project's official postmortem and independently verified by Aikido, Snyk, StepSecurity, and Wiz. The chain has three stages.
Stage one: staging the payload. The attacker created a GitHub fork of the TanStack router repository and embedded a malicious payload inside an orphaned commit that would not appear in a standard git log review. Orphaned commits exist in the object store but have no branch or tag reference pointing to them, which makes them easy to overlook during code review.
Stage two: GitHub Actions exploitation via pull_request_target. The attacker submitted a pull request that triggered the pull_request_target workflow. This GitHub Actions trigger is famously dangerous because it runs with the permissions of the base repository, not the fork, even when the PR originates from an untrusted contributor. By combining this with GitHub Actions cache poisoning across the fork/base trust boundary, the attacker was able to inject the orphaned payload into the build environment. From there, they extracted a live OIDC token from the runner process in memory.
Stage three: trusted publishing exploitation and self-propagation. The stolen OIDC token allowed the attacker to mint a short-lived npm publish token using the npm "trusted publishing" flow, which is specifically designed to allow CI/CD pipelines to publish without storing a long-lived secret. The attacker then enumerated every package published by the same maintainer account, exchanged an OIDC token for a per-package publish token for each one, and published 84 malicious versions across 42 @tanstack/* packages in a six-minute window between 19:20 and 19:26 UTC. No 2FA challenge was triggered because the OIDC flow is explicitly designed to bypass it.
The packages carried valid Sigstore signatures and valid SLSA provenance because they were published via the legitimate infrastructure, just under attacker control.
How the Worm Spread Beyond TanStack
The self-spreading mechanism is what separates Mini Shai-Hulud from a typical one-off compromise. Once the worm had access to a publishable npm token, it scanned for any token with bypass_2fa: true, enumerated all packages associated with that token's maintainer, and repeated the publish cycle. This is how UiPath (65 packages), OpenSearch, and Mistral AI's npm SDK were subsequently hit without requiring the attacker to manually target each project.
The malicious payload itself is designed to steal secrets from the host environment, CI/CD runner variables, cloud provider credential files, and developer dotfiles. It also installs a persistent daemon capable of wiping the developer's home directory on a future trigger, essentially creating a ticking destructive payload in any environment that installed a compromised version.
The PyPI Crossing: A Different Payload Mechanism
The npm and PyPI sides of this attack are architecturally distinct, which matters for detection and remediation.
On the npm side, the payload is injected into the package tarball during the publish step. It executes as part of the install lifecycle, meaning npm install is the trigger.
On the PyPI side, Mistral AI and Guardrails AI were the primary victims. Here the mechanism is different: the malicious code does not live in the wheel or sdist directly. Instead, it is a Python dropper that fires on module import. When your application runs import mistralai or import guardrails, the dropper silently fetches transformers.pyz from an attacker-controlled domain and executes it with python3. This means a clean pip install audit of the package contents would not necessarily catch the exfiltration logic because the payload is remote-fetched at runtime, not present in the distribution artifact.
This design also means that scanning tools that only inspect what is inside a wheel file will miss it. Runtime behavior analysis or network egress monitoring at the process level is needed to catch the dropper variant.
Why SLSA Provenance Did Not Save Anyone
SLSA (Supply chain Levels for Software Artifacts) provenance attestations are increasingly treated as a strong signal of package trustworthiness. Level 3 provenance means the build happened in a hardened, isolated environment and the attestation is cryptographically signed.
The Mini Shai-Hulud attack is the first documented case where an npm worm produced valid SLSA Level 3 attestations for malicious packages. The reason this was possible is that the attacker did not need to fake the provenance. They stole the OIDC token from inside the legitimate GitHub Actions runner, then used that token with the legitimate Sigstore stack to generate a real certificate. The signature is valid. The provenance is real. The packages are malicious.
This should prompt a re-evaluation of what SLSA provenance actually guarantees. It verifies that a package was built by a specific workflow in a specific repository. It does not verify that the workflow was not compromised at the time of the build, and it does not verify that the source code fed into that workflow was free of injected payloads. Provenance is a necessary condition for trust, not a sufficient one.
Affected Packages and Versions
The full list is tracked by multiple vendors, but the highest-impact packages by download volume include:
@tanstack/react-router (12M+ weekly downloads), @tanstack/router-core, @tanstack/react-query, and 39 other packages in the @tanstack scope were affected in the npm window. All malicious versions were published between 19:20 and 19:26 UTC on May 11.
On PyPI, mistralai and guardrails-ai received the dropper payload. The Mistral team published a security advisory confirming the affected version range and confirming that the transformers.pyz remote fetch has since been blocked at the network level via domain takedown.
Immediate Remediation Steps
If you depend on any of the affected packages, the priority actions are:
First, lock to a known-good version. Both the TanStack team and Mistral have published specific version ranges that are clean. Do not rely on semver ranges until you have confirmed the range you are pulling from predates or postdates the attack window.
Second, audit your CI/CD for pull_request_target usage. Any workflow using this trigger that also has access to secrets, tokens, or cloud credentials is a potential attack surface. StepSecurity's Harden Runner can detect OIDC token exfiltration at the runner level.
Third, review your npm publish token configuration. Any token with bypass_2fa: true and broad maintainer scope significantly expands your blast radius if an OIDC session is stolen. Scope tokens to individual packages where the tooling supports it.
Fourth, add runtime egress monitoring for your Python workers. The dropper pattern relies on fetching a remote .pyz file at import time. An anomalous outbound connection from a Python process to an unknown domain during application startup is the telltale signal.
Fifth, do not assume SLSA attestation is sufficient for trust. Treat it as one signal among several, not as a final gate. Combine it with reproducible build verification, dependency pinning by hash, and behavioral analysis.
The Bigger Pattern
Mini Shai-Hulud is not an isolated incident. It is the maturation of a threat pattern that has been building since at least 2023: attackers targeting CI/CD infrastructure rather than the packages themselves. When GitHub Actions workflows are the publishing mechanism, and when OIDC trusted publishing is the authentication mechanism, the security boundary shifts from "who holds the npm token" to "who controls what code runs inside the workflow." That is a harder boundary to defend.
TeamPCP has demonstrated with two campaigns now that they have a playbook for this class of attack. The Pwn Request vector, cache poisoning, OIDC extraction, and self-propagating publish are repeatable steps. They will be used again against other ecosystems and other registries. PyPI's trusted publishing model (via OIDC to PyPI, not GitHub tokens) is structurally similar enough that an equivalent attack targeting Python-native CI pipelines is a realistic near-term threat.
The open source ecosystem needs provenance that survives a compromised build environment. That requires either reproducible builds that can be independently verified, or signed commits that trace all the way to the source tree included in the build, not just the workflow identity.
Until that infrastructure exists at scale, defense in depth through runtime monitoring, aggressive version pinning, and CI/CD hardening is the most practical posture available.
Contra Collective specializes in enterprise software architecture, AI infrastructure, and secure development tooling. If your team needs a supply chain security audit or help hardening CI/CD pipelines, contact us.
More from the lab.
Meta and Microsoft Just Cut Internal Claude Spending: What the AI Cost Math Actually Shows
Reports this week say Meta has cut its internal Claude user base roughly in half and Microsoft has trimmed its Anthropic spending budget by about a third, steering employees toward GitHub Copilot instead. Neither company is claiming Claude got worse. They are claiming it got too expensive to run at internal scale, and that distinction matters a great deal if you are budgeting your own AI tool stack for next year.
Grok Build vs Claude Code: Is xAI's Coding Agent Actually a Threat (October 2026)
xAI's Grok Build is a terminal based coding agent clearly built with one competitor in mind: Claude Code. It runs in your CLI, supports parallel agent sessions, and is priced in a way that signals xAI wants the same enterprise coding budget Anthropic has been winning. Whether it earns that budget depends on more than a feature checklist.
Mistral Large 4, Le Chonk: Europe's 1 Trillion Parameter Bet Against Chinese Open Weights
Mistral just previewed Large 4, nicknamed Le Chonk internally, a 1 trillion parameter, natively multimodal model with only 49 billion active parameters at inference time. Mistral's own claim is specific: best open weights model out of the US or Europe on aggregated benchmarks, with particular strength in cyber defense, manufacturing, and finance workloads. The open weights release is still pending, which matters as much as the benchmark claim itself.