TanStack had two-factor on every maintainer account. They used npm OIDC trusted publishing, the control meant to retire long-lived publish tokens. Their releases shipped with valid provenance attestations.
On May 11, 2026, an attacker published 84 malicious versions across 42 @tanstack/* packages anyway, including @tanstack/react-router, which moves over 12 million weekly downloads (TanStack postmortem, Snyk). The malicious versions carried the same kind of valid provenance signal the legitimate releases do.
OpenAI is the downstream consequence. Two employee devices installed a poisoned @tanstack/* version. OpenAI says the incident did not affect customer data, production systems, intellectual property, or deployed software, but it did expose limited credential material and signing-certificate-related material in repositories accessible to those employees. OpenAI is re-signing its applications with new certificates and has given macOS users until June 12, 2026 to update before older desktop app versions may stop functioning (OpenAI, BleepingComputer). They were not the target. They were a consumer of an npm package.
This is the throughline I have been writing toward for months. MCP Servers Have an npm Problem flagged that AI tool registries were replaying npm's 2014. n8n Shipped Three Patch Waves in Two Months walked through what happens when self-hosted automation eats those advisories. The TanStack incident is the one that closes the loop. It says the attack surface stopped being credentials a while ago. It is the build pipeline.
Here is what "everything right" meant, and what failed:
- 2FA on maintainers. Held. No npm token was stolen. No maintainer account was compromised.
- OIDC trusted publishing. Held against stolen long-lived tokens, but not against attacker code already executing inside the publishing runner. The runner minted a short-lived publish token in memory when
id-token: writewas set, and attacker code running in the same job read that token straight out of/proc/<pid>/mem. - Signed provenance. Held. The attacker used the legitimate publishing path, so the malicious packages were validly attested. Provenance proves origin; it does not prove intent.
- Pinned dependencies, scoped permissions. Did not save them. The defect was a
pull_request_targetworkflow that ran fork code in the base repository's cache scope. It is a pattern GitHub's own security guidance has warned about for years (TanStack hardening followup).
The OpenAI blast radius is the part that should change how the rest of us think about this. Their statement says only limited credential material was exfiltrated, no customer data, no production systems, no IP, no software altered. That is the good outcome. The bad outcome is what those two devices could reach: source-code repositories containing signing-certificate-related material (TechCrunch). Two employee laptops, one open-source dependency, and now every macOS ChatGPT user has a software update deadline. OpenAI also notes this was the second certificate-rotation event in two months, following the Axios developer-tool compromise in March, which had already pushed the company toward additional controls (OpenAI Axios response, OpenAI TanStack response).
The actionable takeaway is short. Trusted publishing is necessary and not sufficient. Audit the pull_request_target workflows in your org this week, especially any that touch the Actions cache. Purge caches on repositories where untrusted code could have written into a cache later restored by release jobs. Split build and publish jobs so the job with id-token: write does not restore or execute artifacts influenced by untrusted pull requests. Treat OIDC tokens as runtime secrets that leak through process memory, not as credentials that live in a vault. Plan for code-signing certificate rotation as a recurring event, not an emergency. And read Your MCP Configs Are an Attack Surface Now if you have not, because the same campaign hit there too.
See also: MCP Servers Have an npm Problem, n8n Shipped Three Patch Waves, Your MCP Configs Are an Attack Surface.
The three-link chain
The TanStack postmortem is precise about how the attack worked. Three known weaknesses, each documented elsewhere, combined to bridge the trust boundaries each one assumed someone else was holding.
Link 1: pull_request_target Pwn Request. The attacker forked TanStack/router, renamed the fork to evade fork-list searches, opened PR #7378 against main, and triggered TanStack's bundle-size.yml workflow. That workflow used pull_request_target, which runs in the context of the base repository instead of the fork. It checked out the PR's merge ref and executed fork-controlled code with base-repo permissions (Snyk).
Link 2: GitHub Actions cache poisoning. The fork code ran pnpm install, then saved a 1.1 GB poisoned pnpm store cache under a key that matched what release.yml would later look up on the next push to main. The attacker then force-pushed the PR back to a no-op state and closed it. The visible PR was clean. The cache was not. actions/cache@v5's post-job save is not gated by the workflow's permissions: block; it uses a runner-internal token. Setting permissions: contents: read does not block cache writes (Appwrite analysis).
Link 3: OIDC token extraction from runner memory. When an unrelated legitimate PR was merged to main days later, release.yml started, restored the poisoned cache, and ran the malicious binaries during the build phase. Those binaries located the GitHub Actions Runner.Worker process via /proc/*/cmdline, read /proc/<pid>/maps and /proc/<pid>/mem to dump worker memory, extracted the OIDC token, and used it to authenticate POST requests directly to registry.npmjs.org. The legitimate Publish Packages step was bypassed entirely. The TanStack postmortem notes the malware used "the same memory-extraction technique (and verbatim Python script, with attribution comment)" from the tj-actions/changed-files compromise of March 2025. The attacker did not invent novel tradecraft. They recombined published research.
Why this is not a TanStack defect class
The campaign hit far more than TanStack. Aikido Security's malware team detected 373 malicious package-version entries across 169 npm package names in this wave, with downstream impact on Mistral AI, UiPath, OpenSearch, Guardrails AI, and others. OX Security counts over 170 packages across npm and PyPI cumulatively, totaling more than 518 million downloads (Aikido, The Hacker News). The worm self-propagates by using stolen npm OIDC identities and GitHub tokens to republish other packages owned by the victim. In the TanStack path, trusted publishing became the vehicle because the attacker executed inside the legitimate publishing environment. Every malicious version carried valid provenance because the attacker was publishing from the legitimate runner.
The campaign is being tracked as Mini Shai-Hulud, attributed to TeamPCP. External researcher detection happened in roughly 20 to 26 minutes (Orca Security). That is the only good number in this incident.
What to actually change this week
- Audit every
pull_request_targetworkflow in your org. If it checks out fork code, rewrite it. The GitHub-recommended pattern isworkflow_runagainst artifacts from a sandboxedpull_requestjob. TanStack's hardening PR removedpull_request_targetfrom CI entirely. - Purge existing GitHub Actions caches on any repo where
pull_request_targetworkflows write the cache. The poison can already be there. - Pin third-party actions to commit SHAs, not tags. TanStack had not. Their hardening PR fixed it.
- Treat
id-token: writeworkflows as memory-sensitive. No untrusted code, restored cache, generated binary, or third-party install script should execute in the same job before the token is minted. Isolate publish steps in a minimal job that does nothing except verify inputs and publish. - If you ship signed artifacts, plan for certificate rotation as a routine operation, not a fire drill. OpenAI's June 12 deadline is the model. Build the rotation runbook before you need it.
The reframing
OIDC trusted publishing was supposed to retire the long-lived npm token. It did. The attacker stopped trying to steal a long-lived token and started minting a short-lived one inside a hijacked runner. The control worked. The threat model moved.
This is the agent-tooling supply chain story I keep returning to. The credentials are getting harder to steal, so the attack moves to the build pipeline. Each new control narrows the attack surface in one place and reveals a new one elsewhere. The job is to keep the defensive iteration cycle shorter than the attacker's research cycle, and to assume the build pipeline is in scope every time.
References
- TanStack. "Postmortem: TanStack npm supply-chain compromise." May 12, 2026. https://tanstack.com/blog/npm-supply-chain-compromise-postmortem
- TanStack. "Hardening TanStack After the npm Compromise." May 13, 2026. https://tanstack.com/blog/incident-followup
- BleepingComputer. "OpenAI confirms security breach in TanStack supply chain attack." May 14, 2026. https://www.bleepingcomputer.com/news/security/openai-confirms-security-breach-in-tanstack-supply-chain-attack/
- TechCrunch. "OpenAI says hackers stole some data after latest code security issue." May 14, 2026. https://techcrunch.com/2026/05/14/openai-says-hackers-stole-some-data-after-latest-code-security-issue/
- PCMag. "OpenAI Tells Mac Users to Update Apps After Software Supply Chain Attack." May 14, 2026. https://www.pcmag.com/news/openai-tells-mac-users-to-update-apps-after-software-supply-chain-attack
- Snyk. "TanStack npm Packages Hit by Mini Shai-Hulud." May 12, 2026. https://snyk.io/blog/tanstack-npm-packages-compromised/
- Aikido Security. "Mini Shai-Hulud Is Back: npm Worm Hits over 160 Packages." May 13, 2026. https://www.aikido.dev/blog/mini-shai-hulud-is-back-tanstack-compromised
- Orca Security. "TanStack and 160+ npm Packages Compromised." May 13, 2026. https://orca.security/resources/blog/tanstack-npm-supply-chain-worm/
- The Hacker News. "Mini Shai-Hulud Worm Compromises TanStack, Mistral AI, UiPath." May 13, 2026. https://thehackernews.com/2026/05/mini-shai-hulud-worm-compromises.html
- StepSecurity. "tj-actions/changed-files compromise." March 2025. https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised
- Appwrite. "The TanStack npm attack shows how fragile modern build systems are." May 12, 2026. https://appwrite.io/blog/post/tanstack-start-npm-supply-chain-attack
- OpenAI. "Our response to the TanStack npm supply chain attack." May 14, 2026. https://openai.com/index/our-response-to-the-tanstack-npm-supply-chain-attack/
- OpenAI. "Axios developer tool compromise." March 2026. https://openai.com/index/axios-developer-tool-compromise/