Un aggiornamento Dependabot ha pubblicato un worm. 22 pacchetti.
Un bot apre una pull request.
Un bot apre una pull request. Un umano la unisce 24 minuti dopo. 95 minuti dopo, un worm ha pubblicato 110 versioni malevole dei suoi 22 pacchetti npm, a suo nome, con un token trovato nella sua CI.
Leggi l'edizione scritta (inglese) ↗
Contenuto di questo video
- Un bot, un umano, un worm
- Come è successo, perché npm lo ha permesso, di chi è la colpa
- Cronologia: la cache avvelenata
- 21:48 — l'aggiornamento di Dependabot
- Perché funziona
Trascrizione tradotta
Tradotto dalla narrazione originale inglese. L'audio e i sottotitoli disponibili sono controllati da YouTube.
Un bot, un umano, un worm
0:00 Un bot apre una pull request; un umano la unisce ventiquattro minuti dopo. Novantacinque minuti dopo, un worm ha pubblicato centodieci versioni dei suoi pacchetti, come lui. Il postmortem di TanStack ha i timestamp upstream, quello del manutentore downstream ha il resto, e Hacker News gli dà undici cento punti e un nome: Mini Shai-Hulud. Come succede, perché npm lo permette, di chi è la colpa.
Come è successo, perché npm lo ha permesso, di chi è la colpa
0:21 Questo è The Daily Diff, postmortem. 11 maggio, mattina. Un fork rinominato apre una pull request contro TanStack Router. Si chiude entro l'ora, ma un workflow di benchmark ha già eseguito il suo codice e
Cronologia: la cache avvelenata
0:33 salvato una cache avvelenata sotto la chiave che userà il workflow di rilascio. Diciannove-venti. Una fusione legittima esegue il rilascio. La cache ritorna, un binario legge la memoria del runner, preleva il token di pubblicazione e spedisce ottantaquattro versioni su quarantadue pacchetti, con provenienza valida. I test falliscono. Pubblica comunque. Diciannove e quarantasei, un ricercatore di StepSecurity presenta il problema; entro le nove UTC tutto è deprecato e l'avviso è fuori.
0:55 Deprecato non significa sparito: npm si rifiuta di de-pubblicare qualsiasi cosa con dipendenti, quindi rimane installabile per ore. Ventuno e quarantotto. In un progetto di dati aeronautici a nove stelle, Dependabot apre la sua pull request di routine: aggiorna il gruppo delle dev-dependencies, tredici aggiornamenti. Due sono versioni avvelenate di TanStack. Ventidue e dodici: unito. Il workflow di pubblicazione esegue npm C-I con il token in
21:48 — l'aggiornamento di Dependabot
1:15 scope; uno script di preparazione lo legge, e alle ventidue e diciassette il worm pubblica come lui. Cinque versioni di ogni pacchetto che il token raggiunge, anche un vecchio side project: un token classico per tutto. Centodieci versioni in novantacinque minuti. Lo scopre via email, dopo mezzanotte. Perché funziona. Uno: npm install esegue gli script del ciclo di vita di sconosciuti per impostazione predefinita, e lo script di preparazione di una dipendenza git conta.
1:39 Due: il worm vuole una cosa: un token che pubblichi senza un secondo fattore. Poi chiede al registro cos'altro possiede quel manutentore, e ripubblica tutto con se stesso all'interno. Tre: niente nella catena è una persona.
Perché funziona
1:51 Un bot propone, una pipeline installa, e il worm restituisce il favore: i suoi rami di dead-drop si chiamano dependabot slash github-actions slash fremen. git blame. Il modello di installazione di npm, cinquantacinque percento: script eseguiti all'installazione, il deprecato rimane installabile, esistono token di bypass a due fattori. La CI di TanStack, venticinque: un workflow target di pull request non auditato che esegue codice forkato con accesso in scrittura alla cache. L'abitudine all'aggiornamento, quindici: tredici aggiornamenti uniti in ventiquattro minuti, token nella stanza.
2:17 Dependabot, cinque: così fidato che il worm indossa la sua uniforme.
git blame
2:20 Raggio di esplosione: quarantadue pacchetti TanStack. Ventidue downstream, da un progetto con nove stelle. Oltre centosessanta a livello di ecosistema una volta che il worm raggiunge Mistral. Ogni versione upstream portava una firma valida: costruita dall'ufficiale pipeline. Vero. Verdetto, postmortem: SHIP IT. Entrambi i manutentori pubblicano postmortem con timestamp entro un giorno; entro tre, la pipeline downstream installa con ignore-scripts, separa build da publish e elimina il token a lunga durata.
Raggio di esplosione
2:47 Le impostazioni predefinite di npm non si sono mosse. Lunedì: ignore-scripts all'installazione e il token di pubblicazione fuori dal job che lo esegue. Mandatemi l'incidente di cui non vi è ancora permesso parlare, nei commenti, o su thedailydiff.dev. E questo è il diff per oggi.
Verdetto
3:00 Sono Niko di Axrisi. Unite responsabilmente.
Fonti
- TanStack postmortem (Tanner Linsley, May 11, refined May 15)tanstack.com
- TanStack "Hardening TanStack After the npm Compromise" (May 12)tanstack.com
- TanStack/router#7383 — the StepSecurity detection issuegithub.com
- Downstream incident post, @squawk/* (May 12)github.com
- Downstream hardening post (May 14)github.com
- The Dependabot PR #246 (opened 21:48 UTC, merged 22:12)github.com
- @tan_stack advisory post, 21:19 UTCx.com
- StepSecurity — worm internals, bypass_2fa search, Dependabot-style branch nameswww.stepsecurity.io
- Socketsocket.dev
- Aikido — "over 160 packages, including Mistral"www.aikido.dev
- Hacker News (1,097 points)news.ycombinator.com



