Uma atualização do Dependabot publicou um worm. 22 pacotes.
Um bot abre um pull request.
Um bot abre um pull request. Um humano funde-o 24 minutos depois. 95 minutos depois disso, um worm publicou 110 versões maliciosas dos seus 22 pacotes npm, em seu nome, com um token que encontrou na sua CI.
Ler a edição escrita (Inglês) ↗
O que este vídeo aborda
- Um bot, um humano, um worm
- Como aconteceu, porque o npm o permitiu, quem é o culpado
- Cronologia: a cache envenenada
- 21:48 — a atualização do Dependabot
- Porque funciona
Transcrição traduzida
Traduzido da narração original em inglês. Áudio e legendas disponíveis são controlados pelo YouTube.
Um bot, um humano, um worm
0:00 Um bot abre um pull request; um humano funde-o vinte e quatro minutos depois. Noventa e cinco minutos depois, um worm publicou cento e dez versões dos seus pacotes, como ele. O post-mortem da TanStack tem os timestamps upstream, o mantenedor downstream tem o resto, e o Hacker News dá-lhe mil e cem pontos e um nome: Mini Shai-Hulud. Como acontece, porque o npm o permite, quem é o culpado.
Como aconteceu, porque o npm o permitiu, quem é o culpado
0:21 Este é o The Daily Diff, post-mortem. 11 de maio, manhã. Um fork renomeado abre um pull request contra o TanStack Router. Fecha em menos de uma hora, mas um fluxo de trabalho de benchmark já executou o seu código e
Cronologia: a cache envenenada
0:33 guardou uma cache envenenada sob a chave que o fluxo de trabalho de lançamento usará. Dezanove e vinte. Uma fusão legítima executa o lançamento. A cache volta, um binário lê a memória do runner, levanta o token de publicação, e envia oitenta e quatro versões em quarenta e dois pacotes, com proveniência válida. Os testes falham. Publica de qualquer forma. Dezanove e quarenta e seis, um investigador da StepSecurity regista o problema; às nove UTC tudo é obsoleto e o aviso é emitido.
0:55 Obsoleto não significa desaparecido: o npm recusa-se a despublicar qualquer coisa com dependentes, portanto, permanece instalável durante horas. Vinte e uma e quarenta e oito. Num projeto de dados de aviação de nove estrelas, o Dependabot abre o seu pull request de rotina: atualizar o grupo de dev-dependências, treze atualizações. Duas são versões envenenadas do TanStack. Vinte e duas e doze: fundido. O fluxo de trabalho de publicação executa o npm C-I com o token em
21:48 — a atualização do Dependabot
1:15 âmbito; um script de preparação lê-o, e às vinte e duas e dezassete o worm publica como ele. Cinco versões de cada pacote que o token alcança, até um antigo projeto secundário: um token clássico para tudo. Cento e dez versões em noventa e cinco minutos. Ele descobre por email, depois da meia-noite. Porque funciona. Um: npm install executa scripts de ciclo de vida de estranhos por padrão, e o script de preparação de uma dependência git conta.
1:39 Dois: o worm quer uma coisa: um token que publica sem segundo fator. Então pergunta ao registo o que mais esse mantenedor possui, e republica tudo com ele mesmo dentro. Três: nada na cadeia é uma pessoa.
Porque funciona
1:51 Um bot propõe, um pipeline instala, e o worm retribui o favor: os seus ramos de dead-drop são nomeados dependabot barra github-actions barra fremen. git blame. Modelo de instalação do npm, cinquenta e cinco por cento: scripts executados na instalação, obsoleto permanece instalável, existem tokens de bypass de dois fatores. CI da TanStack, vinte e cinco: um fluxo de trabalho de destino de pull request não auditado executando código de fork com acesso de escrita à cache. O hábito de atualizar, quinze: treze atualizações fundidas em vinte e quatro minutos, token na sala.
2:17 Dependabot, cinco: tão confiável que o worm veste o seu uniforme.
git blame
2:20 Raio de explosão: quarenta e dois pacotes TanStack. Vinte e dois downstream, de um projeto com nove estrelas. Mais de cento e sessenta em todo o ecossistema assim que o worm chega ao Mistral. Cada versão upstream carregava uma assinatura válida: construída pelo oficial pipeline. Verdade. Veredito, post-mortem: SHIP IT. Ambos os mantenedores publicam post-mortems com timestamps num dia; em três, o pipeline downstream instala com ignore-scripts, divide a construção da publicação, e elimina o token de longa duração.
Raio de explosão
2:47 Os padrões do npm não mudaram. Segunda-feira: ignore-scripts na instalação, e o token de publicação fora do trabalho que o executa. Envia-me o incidente sobre o qual ainda não te é permitido falar, nos comentários, ou em thedailydiff.dev. E essa é a diferença para hoje.
Veredito
3:00 Sou o Niko da Axrisi. Funde com responsabilidade.
Fontes
- 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



