- 21:48 UTC Dependabot opens PR #246: bump the dev-dependencies group, 13 updates (2 poisoned)
- 22:12 UTC merged · npm ci runs with NPM_TOKEN in scope · prepare script takes it
- 22:17–23:52 the worm publishes 110 versions across 22 packages, as the maintainer
+ 03:37 UTC npm removes all 110 · --ignore-scripts, split jobs, OIDC within 3 daysA bot opens a pull request; a human merges it twenty-four minutes later. Ninety-five minutes on, a worm has published a hundred and ten versions of his packages, as him. TanStack's postmortem has the upstream timestamps, the downstream maintainer's has the rest, and Hacker News gives it eleven hundred points and a name: Mini Shai-Hulud. How it happens, why npm allows it, who gets the blame.
May 11th, morning. A renamed fork opens a pull request against TanStack Router. It closes within the hour, but a benchmark workflow has already run its code and saved a poisoned cache under the key the release workflow will use. Nineteen-twenty. A legitimate merge runs the release. The cache comes back, a binary reads the runner's memory, lifts the publish token, and ships eighty-four versions across forty-two packages, with valid provenance. Tests fail. It publishes anyway. Nineteen forty-six, a StepSecurity researcher files the issue; by nine UTC everything is deprecated and the advisory is out. Deprecated is not gone: npm refuses to unpublish anything with dependents, so it stays installable for hours.
Twenty-one forty-eight. In a nine-star aviation-data project, Dependabot opens its routine pull request: bump the dev-dependencies group, thirteen updates. Two are poisoned TanStack versions. Twenty-two-twelve: merged. The publish workflow runs npm ci with the token in scope; a prepare script reads it, and at twenty-two-seventeen the worm publishes as him. Five versions of every package the token reaches, even an old side project: one classic token for everything. A hundred and ten versions in ninety-five minutes. He finds out by email, after midnight.
Why it works. One: npm install runs strangers' lifecycle scripts by default, and a git dependency's prepare script counts. Two: the worm wants one thing: a token that publishes without a second factor. Then it asks the registry what else that maintainer owns, and republishes all of it with itself inside. Three: nothing in the chain is a person. A bot proposes, a pipeline installs, and the worm returns the favour: its dead-drop branches are named dependabot/github_actions/format/fremen.
git blame. npm's install model, fifty-five percent: scripts run on install, deprecated stays installable, two-factor-bypass tokens exist. TanStack's CI, twenty-five: an unaudited pull request target workflow running fork code with write access to the cache. The bump habit, fifteen: thirteen updates merged in twenty-four minutes, token in the room. Dependabot, five: so trusted the worm wears its uniform. Blast radius: forty-two TanStack packages. Twenty-two downstream, from a project with nine stars. Over a hundred and sixty ecosystem-wide once the worm reaches Mistral. Every upstream version carried a valid signature: built by the official pipeline. True. Verdict, postmortem: SHIP IT. Both maintainers post timestamped postmortems within a day; within three, the downstream pipeline installs with ignore-scripts, splits build from publish, and drops the long-lived token. npm's defaults haven't moved.
Monday: ignore-scripts on install, and the publish token out of the job that runs it. Send me the incident you're still not allowed to talk about, in the comments, or at thedailydiff.dev.
Verdict: SHIP IT — timestamped postmortems in 24 h · scripts off, token out of the install job in 3 days
Sources
https://tanstack.com/blog/npm-supply-chain-compromise-postmortem
https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem
https://github.com/TanStack/router/issues/7383
https://x.com/tan_stack/status/2053948103766716630
https://github.com/neilcochran/squawk/pull/246
https://github.com/neilcochran/squawk/discussions/251
https://github.com/neilcochran/squawk/pull/248
https://github.com/neilcochran/squawk/discussions/264
https://tanstack.com/blog/incident-followup
https://www.aikido.dev/blog/mini-shai-hulud-is-back-tanstack-compromised
https://safedep.io/mass-npm-supply-chain-attack-tanstack-mistral/
https://news.ycombinator.com/item?id=48100706
And that's the diff for today. I'm Niko from Axrisi. Merge responsibly.
YouTube · thedailydiff.dev · forward this to the intern who deployed on Friday.

