Table of Contents
On May 11, 2026, a worm quietly burrowed into the npm ecosystem. Within 6 minutes, 42 TanStack packages were compromised. This wasn’t a zero-day exploit — it was a precisely engineered supply chain attack carrying something no malicious package had ever possessed before: a valid SLSA Build Level 3 provenance attestation.
TL;DR
- Attack codename: Mini Shai-Hulud, executed by the TeamPCP group
- Timeline: May 11, 2026 — attack completed in under 6 minutes
- Direct impact: 42 TanStack npm packages compromised
- Total scope: 170+ npm/PyPI packages affected
- Scale: Cumulative download count exceeding 518 million
- Technical first: First malicious package cluster with valid SLSA Build Level 3 provenance
- Attack chain: GitHub Actions
pull_request_targetcache poisoning → OIDC token extracted from/proc/<pid>/mem→ self-propagating worm
What Happened
TeamPCP launched the Mini Shai-Hulud supply chain attack targeting TanStack — the widely-used frontend toolkit family including TanStack Query (formerly React Query), TanStack Router, and TanStack Table.
Rather than directly compromising TanStack’s source code, the attackers exploited a structural weakness in GitHub Actions workflow configuration: the pull_request_target event trigger. This trigger executes workflows in the context of the base branch with elevated permissions, and through cache poisoning, attackers injected malicious code into a trusted workflow execution environment.
Once inside, the attack read OIDC (OpenID Connect) tokens directly from /proc/<pid>/mem — the Linux in-memory filesystem. These tokens are GitHub Actions’ credentials for authenticating package publications to registries like npm. With a valid token, the attackers could publish packages as the official TanStack identity.
The worm component then enabled self-propagation: malicious code spread laterally from one package to its dependencies, sweeping through 42 packages in 6 minutes and ultimately affecting 170+ packages across npm and PyPI.
Why This Matters
Download counts represent real exposure
518 million cumulative downloads is not a theoretical number. Modern CI/CD pipelines reinstall dependencies on every build. Any project that installed affected packages during the attack window may have executed malicious code in development machines or build environments.
SLSA provenance weaponized
SLSA (Supply chain Levels for Software Artifacts) is Google’s supply chain security framework; Build Level 3 certifies that the build process is auditable and tamper-proof. Many security tools and policies use SLSA provenance as a trust signal.
Mini Shai-Hulud is the first malicious package cluster with valid SLSA Build Level 3 provenance. The attackers obtained a legitimate attestation by hijacking a legitimate build process — a fundamental crack in the “trust the signature” assumption.
Worm behavior changes the threat model
Previous supply chain attacks were largely passive: plant the malicious package and wait for downloads. Mini Shai-Hulud’s worm behavior made the attack actively propagate, compressing the defensive response window to minutes. No human monitoring system can react at that speed.
Technical Perspective
Attack flow
graph TD
A[Attacker submits malicious PR] --> B[Triggers pull_request_target workflow]
B --> C[Cache poisoning injects malicious code]
C --> D[Executes in trusted environment]
D --> E[Reads OIDC token from /proc/pid/mem]
E --> F[Publishes malicious versions as legitimate identity]
F --> G[Worm self-propagates to dependent packages]
G --> H[42 packages compromised in 6 minutes]
The pull_request_target trap
pull_request_target was designed to let external PRs trigger limited workflows (such as applying labels), but it executes in the base branch context with access to secrets and tokens. Many projects combined this trigger with build steps for convenience, inadvertently opening a backdoor.
The fix: strictly limit pull_request_target workflows to lightweight tasks that require no secrets. Build and publish pipelines should be triggered by push to protected branches only.
In-memory token extraction
Linux’s /proc virtual filesystem allows processes with sufficient permissions to read the memory of other processes. In GitHub Actions’ shared execution environment, this provides a channel to bypass environment variable protections and extract tokens directly from memory — a known technique with demonstrated real-world destructive impact in CI/CD environments.
Points to Watch
-
Platform-level defenses from npm and GitHub: Will npm introduce stricter publish rate limits or anomaly detection? Will GitHub modify the default behavior of
pull_request_target? -
SLSA framework revision: After provenance was weaponized, the SLSA community needs to reconsider its trust model. A signature proving “the build process was legitimate” is not enough — we also need to verify “was the person who triggered the build authorized to do so?”
-
Worm-based supply chain attacks becoming normalized: Mini Shai-Hulud’s successful demonstration may spawn imitators. Self-propagation capability significantly raises the threat level of supply chain attacks.
-
Damage assessment for affected packages: What did the malicious versions actually execute in active CI environments? Data exfiltration, backdoor implantation, or proof-of-concept only? Full post-incident reports are worth tracking.
References
Answers come from this article only. Click any prompt below or open the chat at the bottom right.
🇺🇸 English
On May 11th, 2026, something unprecedented happened in the npm ecosystem. A supply chain worm burrowed through 42 TanStack packages — that's React Query, TanStack Router, TanStack Table, and related libraries — all compromised within 6 minutes. By the time anyone detected it, over 170 packages across npm and PyPI had been affected, with a combined download history of more than half a billion times.
But here's what made this attack uniquely terrifying: the malicious packages came with legitimate SLSA Build Level 3 provenance. That's a digital signature essentially saying, "This was built by a trustworthy, auditable process." Except it wasn't. This was the first time a malicious package cluster pulled off something the security community thought shouldn't be possible — spoofing the very attestation designed to prevent supply chain attacks.
## How They Did It
The attackers, a group called TeamPCP, didn't need to break into TanStack's servers. Instead, they exploited a structural flaw in how GitHub Actions workflows are configured.
Most open-source projects use a workflow trigger called `pull_request_target`. It's convenient — it lets you automatically run tests or apply labels on incoming pull requests. The problem? It runs in the context of the main branch with full access to secrets and authentication tokens. If you're not careful, you've essentially handed external contributors a key to your publishing pipeline.
The attack started with a malicious pull request. When GitHub Actions triggered the workflow, the attackers used cache poisoning — they injected malicious code into the build cache. That code then executed in the trusted environment, where it had access to something critical: OIDC tokens. These are the credentials GitHub Actions uses to prove to npm, "Yes, this is really the TanStack maintainer publishing a new version."
Here's where it gets creative. The attackers didn't grab these tokens from environment variables like a normal attacker might. They read them directly from `/proc/pid/mem` — that's the Linux in-memory filesystem. From the machine's perspective, they were just another process looking at another process's memory. Difficult to defend against without major architectural changes.
With a valid OIDC token in hand, they could publish packages to npm under the TanStack identity. And then the worm kicked in. The malicious code didn't just sit in one package — it propagated laterally through dependency chains, reinfecting package after package. Forty-two TanStack packages fell in six minutes.
## Why This Is Serious
Five hundred and eighteen million downloads isn't some abstract number. In modern development, every build reinstalls dependencies. Every CI pipeline, every developer's machine during a fresh checkout — they all pulled down those malicious versions. We're not talking about a handful of affected projects. We're talking about potentially thousands of development environments and build servers running attacker code.
The SLSA provenance weaponization is the deeper problem. SLSA is a framework built by Google and the security community specifically to stop this kind of thing. Build Level 3 means you can audit the entire build process. You can verify that the code is actually what it claims to be.
Except now the attackers have proven that you can have a perfectly valid, auditable build process and still end up with malicious code. The signature is real. The audit trail is legitimate. The process was compromised at the moment it mattered most — when the token was extracted and used. This breaks a fundamental assumption: "If the signature is valid, the code is trustworthy."
The worm behavior itself changes the threat model. Traditional supply chain attacks are passive. You publish a malicious package and wait for people to download it. You might have weeks or months before detection. Mini Shai-Hulud compressed that window to minutes, with automatic, active propagation. No human team can respond at that speed. Detection systems have to be automatic, and they have to work in real time.
## The Technical Details
The `pull_request_target` workflow design was intended for simple, low-risk tasks — applying labels, running lightweight checks. Somewhere along the way, people started using it for actual builds and publishes because it was convenient. That convenience became a liability.
The in-memory token extraction is particularly interesting because it's not new. Linux has always allowed processes to peek at other processes' memory if they have the right permissions. In shared execution environments like GitHub Actions, where multiple tasks might run on the same runner, this is a known attack vector. What's new is seeing it weaponized at this scale in a supply chain context.
The self-propagating aspect is the innovation that separates this from previous attacks. The malicious code didn't just sit idle in the compromised packages. It actively searched for opportunities to spread further, modifying code during the build process to inject itself into downstream packages. That's worm behavior, and it fundamentally accelerates the attack timeline.
## What Comes Next
GitHub and npm will almost certainly implement stronger controls. Publish rate limiting, anomaly detection based on unusual publishing patterns, stricter validation of OIDC tokens — these are all likely responses.
The SLSA framework will need to evolve. Right now it certifies the integrity of the build process itself. After Mini Shai-Hulud, the community needs to ask harder questions: Was the person who triggered this build authorized to do so? Are there unexplained environment accesses? Did the process behave outside its normal parameters? The signature alone isn't enough anymore.
And frankly, we should expect copycats. Mini Shai-Hulud proved that worm-based supply chain attacks are feasible. Once a technique is demonstrated to work at scale, others will adapt it, refine it, and apply it elsewhere.
## The Takeaway
Three things to lock in your mind: First, GitHub Actions `pull_request_target` needs to be locked down tight — limited to essential tasks only, never builds or publishes. Second, even cryptographic signatures and formal security frameworks can be weaponized if the underlying system has gaps. You need defense in depth. And third, the speed of modern attacks means you can't rely on human detection anymore. Your safety net has to be automation, and it has to be fast.
🇹🇼 中文
幾天前,開源維護者最大的惡夢,成真了。
在短短六分鐘裡,一批每週合計下載量超過五千萬次的 npm 套件,被供應鏈攻擊攻陷。但這裡有個弔詭的地方——整個過程中,沒有人被釣魚、沒有密碼外洩,也沒有 token 被直接偷走。更諷刺的是,這些中毒的套件,全都是經過簽署、經過驗證,透過 npm 官方的 trusted publishing 機制正式發布的。而 trusted publishing 這套東西,本來就是為了防範這類攻擊而設計、被官方推薦了將近兩年的最佳實踐。
這次事件被叫做 mini Shai-Hulud。它劫持了 React 生態系裡最大的專案之一,TanStack,的發布管線,然後像蠕蟲一樣,擴散到數百個套件。我們今天就來拆解這條「沒人料到」的攻擊鏈。
先講講 TanStack 原本正常是怎麼發套件的。每當一個 pull request 被合併,就會啟動一個 GitHub Actions 的流程,負責把新版本推上 npm。為了發布,CI 伺服器得先跟 npm 拿一個 publish token。而關鍵在於,為了證明這個請求是合法的,GitHub 自己會簽署一份聲明,說明「這是哪個流程、在哪個 repo、哪個分支上跑的」。npm 收到這份簽署聲明之後,會去比對組織的白名單,全部吻合,才發 token。而且這個 token,只會在 CI 快取裡活幾分鐘就失效。
你看,這設計聽起來滴水不漏。token 又短命、又不經過人手,傳統釣魚攻擊根本沒東西可偷。
那攻擊者是怎麼繞過這一切的?問題不在 token 本身,而在於「觸發條件」怎麼設定。
第一步,攻擊者 fork 了 TanStack 的 repo,開了一個 pull request,然後立刻把它關掉。注意,這只是個 fork,而且這個 PR 從頭到尾沒有任何人看過。但光是「建立 PR」這個動作,就足以啟動發布流程。
為什麼?因為 TanStack 在設定觸發條件時,用了一個叫 `pull_request_target` 的選項。這個選項最危險的地方在於:任何進來的 PR,都會在「主 repo 的上下文」裡、帶著「主 repo 的權限」執行——即使這個 PR 是從外部 fork 建立的。
有了這些權限,攻擊者的程式碼就做了一件事:把一個被投毒的檔案,寫進 CI 伺服器的共享快取裡。這個快取,本來是 GitHub Actions 用來在不同 job 之間,重複使用相依套件的。
然後,就是等待。幾個小時後,一個完全無關的 PR 被合併進 main,觸發了那個藏在快取裡的惡意檔案。它從快取撈出 npm 的 publish token,一口氣投毒了八十四個全新的 TanStack 套件版本。
所以你發現了嗎?攻擊者從頭到尾,沒有碰過 token,也沒有攻破簽署機制。他們只是讓自己的程式碼「住進」了合法流程必經的快取,再等合法流程自己來執行它。
而真正讓這件事從「TanStack 的問題」變成「所有人的問題」的,是感染之後的行為。只要你不小心 `npm install` 了其中一個中毒的套件,惡意程式就會執行,掃描你的系統,搜刮任何值錢的東西。一旦它找到任何 npm 的 publishing token,就用這些 token、以同樣的手法,發布新的中毒版本。
於是攻擊自我複製,跳到下一個維護者身上。第一波受害的,包括 Mister AI、UiPath、OpenSearch 這些公司的維護者;幾小時內,他們也把中毒套件推上了 npm。而且透過其中的 Python SDK,這隻蠕蟲甚至跳出了 npm,感染到了 PyPI。到隔天早上,資安公司 Aikido 已經追蹤到一百六十九個套件、總共三百七十三個中毒版本。
這次的攻擊,還有兩個特別陰險的進化細節。第一,它開始偽造由 Claude Code 的 GitHub app 簽署的 commit,把惡意活動偽裝成維護者早就看習慣的「AI 生成 commit」,讓你更難一眼識破。第二,在被感染的機器上,它會把自己直接嵌進 Claude Code 跟 VS Code 這些開發工具裡。
但最狠的,是它埋了一個所謂的「dead man's switch」,死人開關。在每一台被感染的機器上,只要你一嘗試清理它,它就會反手把你的 home 資料夾清空。這讓事後補救變得格外危險——你照直覺去移除惡意程式,反而可能親手觸發破壞。
好,那從這整件事,我們該記住什麼?
第一,trusted publishing 不是萬靈丹。token 短命、免人手、有簽署驗證,這些統統擋不住「讓程式碼住進 CI 快取、再借合法流程之手執行」這條路徑。
第二,這次的根因,是 `pull_request_target`。它讓來自 fork 的、甚至沒人看過的 PR,帶著主 repo 的權限跟可寫入的共享快取執行。把「發布」這種敏感流程綁在這個觸發條件上,等於自己開了一道後門。
第三,蠕蟲化徹底改變了時間尺度。從 fork 一個 PR,到八十四個套件中毒,只花了六分鐘;一夜之間跨生態系擴散到一百六十九個套件。這個速度,遠遠超過人工監控能反應的極限。而萬一你的機器中了,記住——別貿然手動移除,要在隔離環境裡處理。
Tags
Related Articles
How to Design Safety Layers for an AI Agent: From Keyword Detection to Long-Term Behavioral Monitoring
A breakdown of the defense-in-depth used by Claude Code, Codex, and others: rule-based keyword matching, classifiers, input/output scanning, execution sandboxes, cross-session behavioral monitoring, and the role of system prompts and skills.
10 Weird OSS Projects You Actually Need
From Carbon (code-to-image), nektos/act (run GitHub Actions locally), to Ink (React-based terminal UI) — 10 OSS projects that each solve one specific problem really well.
The Forgotten Developer Who Saved JavaScript: Douglas Crockford and the Story of JSON
Douglas Crockford didn't create JavaScript, but he may be the single most important reason it went from a mocked scripting language to the foundation of the modern web: he formalized JSON, created JSLint, and wrote JavaScript: The Good Parts — a book that showed developers JavaScript actually had a good side.