On May 11, 2026, attackers published 84 malicious versions across 42 TanStack packages, plus mistralai 2.4.6 and guardrails-ai 0.10.1, totaling more than 170 packages and over 518 million cumulative downloads.1 All 84 TanStack versions carried valid SLSA Build Level 3 provenance attestations.2 The attackers did not forge the signature; they stole the OIDC token from the legitimate runner’s memory and asked GitHub to sign the release on their behalf.
The May 11 Wave: What Was Published
The scope was large enough to make anyone running npm install in the prior 48 hours wince. Snyk’s breakdown1 puts the count at 84 malicious versions across 42 @tanstack/* packages, plus mistralai 2.4.6 and guardrails-ai 0.10.1, for a total of more than 170 packages and over 518 million cumulative downloads. The packages were not typosquats or lookalikes. The TanStack versions were published under the real maintainer accounts, with version numbers that followed the real release cadence, and with SLSA provenance files that verified cleanly against npm’s public key infrastructure.
That is the point worth sitting with. npm’s provenance system, introduced to let consumers cryptographically verify that a package was built from a specific GitHub workflow on a specific commit, was designed to make this exact attack impossible. The signature checked out. The workflow name matched. The commit hash was present. The artifact was still malicious.
Attack Chain: From Fork to Signed Malware
The entry point was pull_request_target, a GitHub Actions trigger that runs workflows in the context of the base repository, not the fork. Semgrep’s analysis reconstructs the chain: a contributor opens a PR from a fork, the target workflow runs with base-repo permissions, and the attacker poisons the GitHub Actions cache across the fork-to-base trust boundary. From there, the cached payload executes inside the privileged workflow, gains access to the runner, and extracts a short-lived OIDC token from /proc/<pid>/mem of the runner process.
The token is the pivot. GitHub’s OIDC-based “trusted publishing” lets a workflow authenticate to npm without long-lived secrets; the token is minted by GitHub, scoped to the repository, and valid for minutes. Once the attacker has it, they can publish to npm as the legitimate project. The SLSA attestation is not forged; it is produced by the real TanStack CI runner, running under attacker control, using GitHub’s own signing infrastructure. The provenance is valid because the pipeline was compromised, not because the attacker broke the cryptography.
This is not a subtle distinction. SLSA Build Level 3 attests to the identity of the build pipeline and the immutability of its configuration. It does not attest to the integrity of the runner at the moment the build ran. If the runner is executing attacker-controlled code, the attestation becomes a signed affidavit that a compromised system did exactly what the attacker told it to do.
Why Valid SLSA Provenance Failed
The SLSA framework, particularly at Build Level 3, was marketed as a backstop: verify the attestation, trust the artifact. The Mini Shai-Hulud incident demonstrates that this is a category error. Provenance proves pipeline identity, not pipeline integrity. When the pipeline itself is the threat vector, the signature becomes an endorsement of the attacker’s work.
The architectural issue is that OIDC tokens, while short-lived and scoped, are still bearer tokens extracted from a process running in a CI environment with limited isolation. Once an attacker can read /proc/<pid>/mem, which cache-poisoning inside a workflow trivially enables, the token is theirs until expiry. GitHub’s trusted publishing model assumes the runner is a trusted computing base. The TanStack compromise shows that assumption fails when pull_request_target workflows share cache with forked code.
Payload Anatomy: gh-token-monitor and the Dead-Man’s Switch
The malware itself is where the attacker’s sense of theater meets their operational security. According to The Hacker News, the payload installs a persistent daemon called gh-token-monitor that polls api.github.com/user every 60 seconds. If the stolen token returns HTTP 401 or 403,3 indicating revocation, the daemon executes rm -rf ~/ on the host.
This is not subtle exfiltration. It is a dead-man’s switch designed to punish incident responders for rotating credentials. The moment your security team revokes the compromised token, every infected machine wipes its home directory. The tactic turns a standard remediation step into a denial-of-service event, forcing defenders to choose between leaving active tokens in the wild or triggering data destruction.
The daemon also illustrates the attacker’s confidence in their dwell time. A payload that phones home every minute and self-destructs on token death assumes the token will not be revoked immediately, which in turn assumes the compromise will not be detected for hours or days. Given that these packages collectively accounted for over half a billion lifetime downloads,1 that assumption was well-founded.
From LiteLLM to TanStack: TeamPCP’s Campaign Timeline
StepSecurity, Wiz, and Snyk attribute the May 11 wave to TeamPCP, also tracked as DeadCatx3, PCPcat, ShellForce, and CipherForce. This is the same group that Palo Alto Unit424 identified behind the LiteLLM CI compromise in March 2026, where a poisoned Trivy scanner was used to backdoor the CI pipeline. The pattern is consistent: target AI/ML tooling repositories, compromise the CI system, and use the resulting access to publish malicious artifacts under legitimate project identities.
The LiteLLM incident was a scanner backdoor. The TanStack incident is a CI runner compromise followed by a provenance bypass. Both rely on the same premise: open-source AI tooling projects have complex CI pipelines, accept external contributions, and use automated publishing workflows that trade security for maintainer velocity. TeamPCP has now demonstrated that they can move from poisoning a single tool to extracting OIDC tokens from memory and minting valid SLSA attestations for dozens of packages.
What ‘Trusted Publishing’ Means After This
The industry response to this incident will likely bifurcate. One camp will call it a misconfiguration: “just don’t use pull_request_target with cache sharing,” or “just harden your runner.” The other camp, and the one this analysis belongs to, will recognize it as an architectural gap. If a single cache-poisoning primitive can escalate to full OIDC token extraction and valid provenance issuance, the trusted computing base is too large.
The fix is not obvious. Removing pull_request_target breaks the fork contribution model for many projects. Isolating CI caches per-PR adds operational cost. Requiring manual approval for every release negates the automation that makes trusted publishing attractive. But continuing to treat valid SLSA provenance as a synonym for “safe to install” is no longer tenable after May 11.
The incident is tracked as CVE-2026-45321,2 with a CVSS score of 9.6. The CVE number is useful for scanners and compliance checklists. The more useful artifact is the understanding that cryptographic verification of provenance only shifts the trust boundary. It does not eliminate it. The trust is now in the runner, the workflow configuration, and the cache isolation model. All of those have been shown to fail, and all of them are harder to audit than a signature.
Frequently Asked Questions
Is Mini Shai-Hulud the same campaign as the original Shai-Hulud from 2025?
No. The original Shai-Hulud worm dates to September 2025 and is a separate wave. Mini Shai-Hulud is the May 2026 campaign attributed to the same actor (TeamPCP), but the two used different entry techniques and targeted different projects. Conflating them leads to incorrect IOC matching.
What should incident responders do before revoking stolen tokens on infected machines?
Isolate the host from the network first. Because gh-token-monitor polls GitHub every 60 seconds and runs rm -rf ~/ on 401/403, revoking the token before the host is isolated triggers the dead-man’s switch. The correct order is: disconnect, snapshot for forensics, then revoke. Standard rotate-first playbooks will cause data loss here.
Would a higher SLSA level have stopped this?
SLSA Build Level 4 requires hermetic builds with no network egress and isolated build steps, which would have blocked both the cache-poisoning vector and the /proc/
Were the Python packages (mistralai, guardrails-ai) hit through the same provenance bypass?
The brief identifies them as part of the same 170+ package wave, but PyPI’s trusted-publishing model differs from npm’s: PyPI requires each project to explicitly register the exact workflow filename and repository, which narrows the set of workflows that can mint a token. The npm packages carried the SLSA Level 3 attestations; the Python packages’ compromise path has not been detailed as a provenance bypass in the available reporting, suggesting a different delivery mechanism may have been used for the PyPI side of the campaign.