TanStack Got Hacked—And Nobody Made a Mistake
A sophisticated NPM worm hit TanStack and 160+ packages—with a deadman switch that wipes your PC if you revoke stolen credentials. Here's what actually happened.
Written by AI. Tyler Nakamura

Photo: AI. Tomoko Hayashi
Okay so I went down this rabbit hole at like midnight and I genuinely could not stop reading. You need to hear about this.
A malicious worm called Shai Hulud—yes, like the sandworm from Dune, and yes, that matters later—hit TanStack this week. According to Better Stack's breakdown, this is at least the fourth iteration of this particular attack campaign, and each version has gotten nastier. This one published 84 malicious versions across 42 TanStack packages in just a few minutes. It also hit UiPath, Mistral, and reportedly over 160 other packages, including Python packages like Guardrails AI.
I'm going to explain how it works in a way that doesn't require you to live in a terminal. Because here's the thing—this story isn't really about npm or GitHub Actions or whatever acronyms make your eyes glaze over. It's about the moment you realize that doing the right thing is exactly what gets you destroyed. That realization hit me hard reading through this, and I want you to feel it too.
What happens when you install a poisoned package
When you install one of the compromised packages, a script quietly runs in the background—detached from your install process so nothing looks wrong in your logs. Think of it like someone slipping into your house through a back door while the front door alarm isn't triggered, then locking themselves into your basement.
From there, it does a few things that are genuinely clever in a "oh no" kind of way. It copies itself into your Claude Code hooks folder—that's the AI coding assistant—so that every time you open Claude Code in that project, the malware re-runs. It does the same trick with VS Code's task runner. It also installs an OS-level background service called "GitHub token monitor." That name will matter in a minute.
Then it gets to work stealing basically everything it can find: SSH keys, AWS credentials, cloud provider tokens, crypto wallet files, Slack and Discord data, your shell history, and—this one made me stop scrolling—your Claude Code session history. If you've ever pasted an API key into Claude, or let it read a file that contained credentials, this worm potentially grabbed those too.
Per Better Stack's analysis, the stolen data gets exfiltrated through the Session messenger network, with a backup: it dead-drops the data into GitHub repos. According to their reporting (sourced from security firms including StepSecurity, Socket, Snyk, and Wiz), those backup branches were named after Dune references—which is where the worm's own name comes from.
The part that stopped me cold
Here's the deadman switch, and I want you to really sit with this.
That "GitHub token monitor" service running in the background? It checks your GitHub token every single minute. If the token is still valid: nothing happens. If you've rotated it—if you did the correct security thing and changed your compromised credentials—it runs rm -rf on your entire user directory. Wipes everything.
It also creates an npm token on your behalf with a description that reportedly reads: "if you revoke this token, we will wipe the computer of the owner."
Read that again. The attack is specifically engineered so that your first instinct—change the password, rotate the key, lock it down—triggers destruction. The correct response to a credential compromise becomes the payload trigger. I kept re-reading that section because it felt like I was misunderstanding something. I wasn't.
Better Stack's host put it plainly: "if you revoke these tokens before isolating your machine and removing that background process, the payload can self-destruct your PC."
The right move, if you find yourself here, is: do not touch the tokens until you've killed the background process first. Isolate the machine. Then rotate. That order matters enormously.
How it spreads (the part that scales this from bad to worse)
Stage one is theft. Stage two is replication—and this is where it gets away from "someone got hacked" into "the whole ecosystem has a problem."
The worm looks for npm credentials that can publish packages without requiring two-factor authentication. If it finds them, it scans every package that account can publish to, injects itself, and pushes new infected versions. Basic but effective.
The scarier version is what happens in CI/CD pipelines—the automated systems that test and release software. Modern setups often use something called OIDC (think of it as a system where GitHub can vouch for itself to npm: "yes, I'm the real TanStack repo running the real release workflow"). The idea is you don't store a permanent publish token anywhere risky.
The problem is that once the malware is inside a trusted CI environment, it can request that same short-lived credential and use it to publish. As Better Stack describes it: "the malware can use the OIDC-related environment that GitHub exposes to the job to request an OIDC JWT token from GitHub's token endpoint. Then it exchanges that JWT token with npm for a short-lived publish token through the npm trusted publishing system."
The package it then publishes is signed with valid provenance, published by a real workflow. Every trust signal says: this is legitimate. Because technically, it is—just running from poisoned code.
How TanStack actually got infected
This is the part I found most fascinating, because TanStack's team didn't make an obvious mistake. The attack required real reconnaissance and patience.
According to TanStack's own postmortem and Better Stack's documentation of it, the attacker created a fork of TanStack Router and renamed it to something generic to avoid detection. They added a malicious commit to the fork that was fake-authored as "Claude" (the AI)—worth noting this detail comes from Better Stack's reporting, which cites TanStack's postmortem directly, though I'd encourage independent verification of the specific fake author identity given how notable it is. The commit message started with [skip ci] to prevent any CI from running immediately.
The next day, they opened a pull request with a totally mundane title: "WIP: simplify history build."
Here's where it gets surgical. TanStack had a GitHub Actions workflow that used a trigger called pull_request_target. Unlike regular pull request triggers, this one runs in the base repo's security context—meaning it has access to the real repo's cache and its GitHub token, even for code coming from a fork. The workflow ran, installed dependencies from the fork's malicious code, and that code poisoned the pnpm package store (pnpm is a package manager, like npm) under the exact cache key that TanStack's release workflow would later use.
Then the attacker reset the branch to match main, closed the PR, and deleted the branch. To any outside observer, nothing happened.
Eight hours later, a TanStack maintainer merged a completely unrelated PR into main. That triggered the release workflow. The release workflow restored the cache—the poisoned one—and suddenly attacker-controlled code was running inside TanStack's official release process. It grabbed an OIDC publish token and pushed 84 malicious versions across 42 packages. The action even failed partway through because unrelated tests broke. It didn't matter. The malicious publishes had already gone out.
Better Stack summed up the chain: "the attacker managed to chain three trust boundaries—the fork PR code poisoned the base repo's cache, that cache was restored inside the real release workflow, and the real release workflow had OIDC permissions which turned into npm publish access."
What I think this actually means
The answer everyone reaches for with supply chain attacks is "better hygiene." Audit your dependencies. Use 2FA. Rotate credentials regularly. All of that is true and none of it would have stopped this.
TanStack had a real workflow. They had OIDC set up—the supposedly better alternative to stored tokens. The attack used their safety infrastructure as the attack surface.
I don't think the takeaway is "nothing works, give up." I think the real move is narrower and more uncomfortable: the pull_request_target trigger is dangerous by design when combined with dependency installation from fork code. That specific combination—trusted context + untrusted code—is the hole this attack crawled through. Pinning that trigger's behavior and sandboxing dependency installs in PR workflows is something developers can actually change.
The Python variant of this attack, per Better Stack's reporting (citing StepSecurity's analysis), adds a locale check—stopping completely if the system language is Russian, and running a destructive command on a random roll of the dice if the machine appears to be from Israel or Iran, paired with playing an audio file at full volume. I couldn't find which audio file, and Better Stack says the same. That behavior is documented in StepSecurity's technical writeup, and if accurate, it's a detail that raises questions I don't have good answers to about who built this and why.
What I do know is this: the npm ecosystem's answer to supply chain attacks has been "build better trust signals." Signed packages. Verified provenance. OIDC publishing. And Shai Hulud just used all of those trust signals to look legitimate while spreading to 160+ packages.
If the thing we built to verify authenticity is now the thing attackers impersonate, what exactly are we trusting?
Tyler Nakamura is Buzzrag's Consumer Tech & Gadgets Correspondent. He covers the technology that actually affects your life—including, apparently, the parts that can wipe your hard drive.
We Watch Tech YouTube So You Don't Have To
Get the week's best tech insights, summarized and delivered to your inbox. No fluff, no spam.
More Like This
Penpot Wants to Fix Design Handoff—Does It Actually?
Better Stack demos Penpot, an open-source design tool that speaks CSS natively. We look at what it solves, what it doesn't, and who should care.
Chrome's HTML-in-Canvas Experiment Might Make the Web Fun Again
Chrome Canary's new HTML-in-Canvas feature lets developers embed interactive DOM elements in WebGL scenes. It's experimental, buggy, and kind of brilliant.
Axios RAT Attack: What Happened and How to Check If You're Hit
A sophisticated remote access trojan infiltrated Axios through a rogue dependency. Here's how the attack worked and what developers need to do now.
TSRX Wants to Replace JSX — But at What Cost?
TSRX is a new syntax layer that lets you write React components with plain if statements and no return. Here's what junior devs actually need to know.
Malware Now Uses Blockchain for Command and Control
Sophisticated malware campaign uses invisible Unicode characters and Solana blockchain transactions to evade detection and communicate with attackers.
GNOME and KDE Together? Linux App Summit Explained
GNOME's Sri and KDE e.V. President Aleix Pol talk Linux App Summit, Flatpak's future, and what it'll actually take to get mainstream apps on Linux.
The Karpathy Loop: When AI Runs 700 Experiments Overnight
Andre Karpathy's AI agent ran 700 experiments while he slept, found bugs he missed, and cut training time 11%. Here's what that means for everyone else.
Anthropic's Claude Mythos Found Thousands of Zero-Days
Anthropic's new Claude Mythos AI discovered thousands of zero-day vulnerabilities, prompting a defensive security initiative before public release.
RAG·vector embedding
2026-05-15This article is indexed as a 1536-dimensional vector for semantic retrieval. Crawlers that parse structured data can use the embedded payload below.