A single PR just hijacked the NPM registry...
Chapters10
Introduces the supply chain attack on open source packages and how it leveraged trusted publishing to compromise many packages.
A single PR exposed a supply-chain flaw that hijacked NPM's publishing flow, spawning a worm across hundreds of packages and forcing a rethink of safe publishing practices.
Summary
Fireship's code breakdown unveils a dramatic NPM supply-chain attack centered on TanStack's release process. The attacker leveraged a fork-and-PR tactic that bypassed strict protections by abusing the pull request target context, grabbing a publish token from the CI cache, and then poisoning dozens of packages. Once published, the malware spread through the ecosystem, leveraging dependencies and even forging commits with the Claude Code GitHub app to blend in. The worm infected developers’ machines, re-executing itself on editor launch, and even triggering a destructive live-nuke of the root directory when tokens expire. TanStack, Mistral AI, UiPath, Open Search, Guardrails AI, and Squawk were among the initial victims, with 373 poisoned versions across 169 packages tracked within 24 hours. The video also highlights mitigation options, notably PNPM’s minimum release age, block exotic subdependencies, and approved builds, as well as a plug for Sentry’s Seir Agent to automate root-cause investigation. Fireship closes with a candid admission that perfect defense may be unlikely, but practical defenses exist for individual developers and teams to cut risk.
Key Takeaways
- Understanding the attack requires following how TanStack’s CI publish token is retrieved: the publish token is stored briefly in the CI cache and used by a malicious PR to trigger publishing.
- The attacker used a fork-and-PR tactic with pull request target context, enabling the compromised code to write a poisoned file into the CI shared cache and steal the npm publish token.
- Hundreds of packages were affected after the first wave, with 373 poisoned versions across 169 packages tracked within hours by security firm Aikido.
- PNPM offers three defenses by default: minimum release age (block releases younger than 24 hours), block exotic subdependencies (reject non-registry sources), and approved builds (block install scripts), which would have mitigated many attack paths.
Who Is This For?
Ideal for JavaScript/TypeScript developers, DevOps engineers, and open-source maintainers who manage npm-style publishing pipelines and rely on CI/CD tokens. It highlights concrete misconfigurations and practical mitigations to reduce blast radius in real-world projects.
Notable Quotes
"Just a few days ago, the worst nightmare of every open-source maintainer finally came true."
—Intro framing for the severity of the incident.
"The poisoned packages were signed, verified, and shipped through npm's trusted publishing feature, which was built primarily to prevent these kinds of attacks."
—Highlights the paradox: trusted tooling was exploited.
"The attacker forked the Tanstack repo, created a pull request, and then immediately closed it."
—Describes the exact leverage point used to trigger the attack.
"The poisoned file was triggered, which grabbed the npm publish token from the cache and used it to take a massive shy hall dump on the 84 brand new compromised Tanstack packages."
—Shows how the token theft enabled mass publication.
"The moment your token expires, it activates war crime mode and nukes your root directory."
—Crisp description of the malware’s destructive trigger.
Questions This Video Answers
- How did a single PR hijack the NPM publishing process in the TanStack attack?
- "What can PNPM do to stop supply-chain malware by default?"
- "What is a dead man switch in malware, and how does it affect developers?"
- "How can teams secure CI publish tokens to prevent token theft in forks?"
- "What is Sentry Seir Agent and how can it help in post-incident investigations?
NPM supply chain attackTanStackPNPMGitHub ActionsCI/CD securitynpm publish tokendead man switchPoisoned packagesOpen-source securitySentry Seir Agent
Full Transcript
Just a few days ago, the worst nightmare of every open- source maintainer finally came true. No, they weren't forced to socialize with the opposite sex. Instead, in just 6 minutes, which I've been arguing for years is actually quite a long time, over 100 packages that collectively get downloaded more than 50 million times a week, were compromised in a supply chain attack where no one was fished, no passwords were leaked, and no tokens were stolen. And to make it even worse, the poisoned packages were signed, verified, and shipped through npm's trusted publishing feature, which was built primarily to prevent these kinds of attacks and has been the recommended publishing setup for almost 2 years now.
In today's video, we'll break down the clever trick that let an attacker hijack the release pipeline of one of the biggest projects in the React ecosystem. We'll see how the malware then spread to hundreds of other packages and learn about the dead man switch, which is now on every infected machine that will nuke your home folder the second you try to clean it up. Heaven help us all. It is May 14th, 2026, and you're watching the code report. Life has been extra exciting lately because every time I wake up, I wonder which one is going to destroy my life first, the rodent poop cruise virus or the mini shy hallude virus.
But thankfully, I'm no poop expert, so I'll stick with breaking down how the shy hallude prairie dogged its little head again in a fairly sophisticated attack that no one saw coming. And it all started with how Tanstack's release process works. Whenever a new pull request is merged, a GitHub actions workflow kicks off, which handles publishing the new version to the mpm registry. But to do that, the continuous integration server needs to get a publish token from npm first. To prove the request is legit, GitHub itself signs a statement saying which workflow is running, in which repo, and on which branch.
NPM then checks that signed statement against the org's allow list and only hands over a token if everything matches. The token then lives for a few minutes in the CI's cache and then quickly becomes stale, so there's nothing for traditional fishing attacks to steal. This sounds bulletproof, but the problem is that the mini shy hulude attack wasn't traditional. Here's how it worked. The attacker forked the Tanstack repo, created a pull request, and then immediately closed it. Even though it was just a fork and the pull request was never seen by anyone, just creating the PR was enough to kick off the publishing workflow.
And this is where the Tanstack team went wrong because when they configured the trigger for the workflow, they used the pull request target option, which meant that any pull request that came in would run in the context of the main repository along with the main repository's permissions, even if the PR was created from a fork. that those permissions were enough to allow the attacker's code to write a poisoned file into the shared cache of the CI server, which is used by GitHub actions to reuse dependencies between jobs. A few hours later, an unrelated pull request was merged into main.
The poisoned file was triggered, which grabbed the npm publish token from the cache and used it to take a massive shy hall dump on the 84 brand new compromised Tanstack packages. But from there, if you were lucky enough to npm install one of those packages, the malware ran and scan your system for anything valuable it could get its grubby little sete on. And if it found any npm publishing tokens, it used those to publish new poison versions with the same hack, which is how a tan stack problem became an everybody problem. The first wave of victims included maintainers at Mistral AI, UiPath, Open Search, Guardrails AI, and Squawk.
Within hours, those companies pushed compromised packages onto the mpm registry as well. And through their Python SDKs, the worm jumped the shark over to Pi. But by the next morning, security firm Aikido was tracking 373 poisoned versions across 169 packages. And the worm was getting even smarter. It started forging commits signed by the Claude Code GitHub app. So, its malicious activity blended in with the AI generated commits maintainers were already used to seeing. And on infected machines, it embedded itself directly into clawed code and VS Code. So even after a developer uninstalled the bad packages, the worm would just re-execute itself the next time they open their editor.
And my favorite part, if you were infected, the malware also installed a background process that would quietly check every 60 seconds whether your stolen GitHub token was still valid. The moment your token expires, it activates war crime mode and nukes your root directory. So, how do we prevent this in the future? Well, the reality is that we probably don't. But there are some things you can do on your end to help your odds. The best would be to use PNPM1 or higher, which comes with two features turned on by default that would have stopped this exact worm from reaching most of you.
The first is minimum release age. It tells PNPM to refuse any packages published less than 24 hours ago, which is long past when most malicious packages are detected and pulled from the registry. The second is block exotic subd dependencies. Normally, every transitive dependency in your project comes from the npm registry. But there's nothing stopping a package from listing a dependency that points at a random git repo or a tarball URL on some attackers S3 bucket. Block exotic subdeps refuses to install anything that doesn't come through a proper registry, which closes one of the most elegant ways for malware to smuggle itself in.
And the third PNPM feature worth using is approved builds. Most npm malware does its damage through install scripts that run automatically when you type npm install. The PNPM11 blocks all of them by default and lets you walk through your dependencies and whitelist the few packages you actually want to let run code. But even when using PNPM, things can still break in production. And that's where Sentry, today's sponsor, can help you out. They just shipped Seir Agent, an AI agent that investigates your production issues for you. is so the next time you get a jump scare Slack notification about a bunch of new errors, you can just ask your agent to investigate the problem instead of manually digging through dashboards and logs yourself.
The agent uses all the context Sentry already has on your system to pull traces, spans, logs, and replays. Then it walks upstream across your services to find the actual root cause. From there, you can work with Seir to draft a fix and open a pull request is so you can spend less time staring at error messages and more time pretending to touch grass. The developers are calling it a self-healing software and you can try it out for free right now during the open beta at century.io/fireship. This has been the code report. Thanks for watching and I will see you in the next one.
More from Fireship
Get daily recaps from
Fireship
AI-powered summaries delivered to your inbox. Save hours every week while staying fully informed.









