‘Não há como impedir’, diz o único gerenciador de pacotes em que esse tipo de coisa acontece regularmente
(kevinpatel.xyz)- Um ataque à cadeia de suprimentos do registro npm expôs milhões de aplicativos corporativos e bilhões de registros de usuários, mas o ecossistema trata isso como algo inevitável
- O Senior Frontend Engineer Mark Vance critica a realidade de depender de 40 níveis de dependências aninhadas de pacotes não verificados até para transformar uma string em maiúsculas
- A tomada de um pacote utilitário abandonado há muito tempo, com injeção de crypto-miner em builds de produção no mundo todo, é tratada como um desastre natural
- O ecossistema Node.js encara uma execução remota de código maliciosa como uma tragédia imprevisível, enquanto equipes de DevOps ficam ocupadas trocando chaves da AWS
- Os ecossistemas de Go, Rust e Web APIs nativas aparecem como contraste, com bibliotecas padrão fortes e verificação criptográfica para reduzir a dependência de terceiros
Sátira sobre ataque à cadeia de suprimentos no npm
- Um ataque à cadeia de suprimentos do registro npm comprometeu milhões de aplicações corporativas e expôs bilhões de registros de usuários, mas os desenvolvedores do ecossistema JavaScript tratam isso como algo “completamente impossível de evitar”
- O Senior Frontend Engineer Mark Vance vê como custo do desenvolvimento moderno de aplicações web a realidade de depender de uma árvore de 40 níveis de dependências aninhadas de pacotes não verificados só para colocar uma única string em maiúsculas
- A tomada de um pacote utilitário abandonado há muito tempo, com a injeção de crypto-miner em builds de produção ao redor do mundo, é tratada como um desastre natural
- O ecossistema Node.js encara uma execução remota de código maliciosa como uma tragédia imprevisível e envia “pensamentos e orações” às equipes de DevOps ocupadas em trocar chaves da AWS
Contraste entre outros ecossistemas e o npm
- Os ecossistemas de Go, Rust e Web APIs nativas reduzem bastante a dependência de código de terceiros com bibliotecas padrão robustas e incluem verificação criptográfica rigorosa na cadeia principal de ferramentas
- Nesses ecossistemas, o contraste é que hoje houve zero casos de um “projeto de fim de semana de um universitário que largou a faculdade” derrubando a infraestrutura logística global
- Um porta-voz do npm afirmou de forma categórica que, em um mundo onde existem agentes maliciosos, isso precisa ser aceito, e que não há política de registro nem guardrails de sandbox de build capazes de impedir isso
- O registro npm é retratado como um registro de código aberto que executa por padrão scripts de instalação arbitrários na máquina local, fazendo a fala do porta-voz se alinhar ao risco estrutural
- No fim, o texto oferece consolo às vítimas, mas conclui dizendo que é preciso manter a resiliência até “a próxima violação inevitável” amanhã de manhã
1 comentários
Comentários no Hacker News
Cada um pode ter sua opinião sobre cooldown, mas boa parte dos ataques recentes à cadeia de suprimentos do npm, incluindo axios e tanstack, poderia ter sido evitada com cooldown
Se você usa Artifactory / Nexus, provavelmente já tem algum cooldown; e, se não tiver, é fácil configurar
Como a maioria das invasões ao npm ou ao PyPI foi removida em poucas horas, cooldown aqui quer dizer “ignorar pacotes lançados há menos de N dias”. Até 1 dia já ajuda, 3 dias é razoável e 7 dias é um pouco excessivo, mas funciona
Para configurar isso, dá para usar a versão mais recente do pnpm, que já inclui cooldown padrão de 1 dia, ou https://pnpm.io/supply-chain-security; se quiser corrigir tudo de uma vez, pode usar https://depsguard.com, que adiciona cooldown e configurações recomendadas para npm, pnpm, yarn, bun, uv e dependabot. Eu sou o mantenedor
Ou então há o https://cooldowns.dev, mais focado especificamente em cooldown, além de scripts para ajudar com configuração local. Tudo é open source ou gratuito
Se você já sabe editar
~/.npmrce afins manualmente, talvez nem precise disso, mas para pessoas próximas que precisam de uma solução com um clique, isso pode evitar o próximo ataqueClaro, quando for preciso corrigir um CVE crítico novo, será necessário contornar o cooldown, e cada ferramenta tem sua forma de fazer isso. Não tenho números exatos, mas nas últimas semanas parece que o risco maior veio mais de ataques à cadeia de suprimentos de software do que de novos CVEs zero-day
O mesmo vale para upgrades periódicos de dependências. Só que há casos em que é preciso atualizar imediatamente, como resposta a vulnerabilidades, e aí eu acho aceitável exigir que o desenvolvedor especifique explicitamente a nova versão desejada
Se todo mundo aplicar um cooldown de 7 dias, isso não só vai explodir mais tarde?
Pensando melhor enquanto escrevo, ainda assim concordo com um cooldown de 10 dias, no sentido de não instalar nada lançado nos últimos 10 dias. Só não acho que isso deva ser tratado como a única mitigação
Fico curioso sobre o que Go ou Rust realmente garantem em comparação com Python/npm. Também pode ser só que Python/npm sejam alvos mais atraentes
Estou cada vez mais tentando evitar qualquer pacote de terceiros
O Maven Central existe há décadas, mas teve pouquíssimos incidentes de roubo de namespace
Você não pode publicar um pacote com groupId
com.ycombinatorsem verificar que possui o domínio ycombinator.com. E, uma vez publicado, o pacote é 100% imutável, mesmo que contenha código malicioso. Claro, essas bibliotecas passam a ser marcadas como vulneráveis em vários lugaresNão entendo como o NPM não conseguiu copiar salvaguardas como as do Maven Central em todo esse tempo
Em vez de haver um conjunto de bibliotecas verificadas distribuídas com a linguagem, a aplicação precisa implementar por conta própria ou buscar em um repositório de pacotes de terceiros. Como passamos anos ensinando as pessoas a evitar NIH, elas acabam pegando um pacote
Isso em si não é necessariamente ruim, mas muitas vezes puxa-se mais código do que o necessário. O ecossistema JS também favorece módulos pequenos, então são precisos muitos módulos, e todo mundo vai empilhando mais coisas por cima, fazendo o grafo de dependências ficar gigantesco. Seja por intenção ou não, a superfície para dar problema é enorme
Outras linguagens já trazem muito mais coisa pronta. Não é que nunca tenham tido bugs ou problemas de segurança, mas, comparado ao que vemos no ecossistema JS, é quase nada. O grafo de dependências externas é muito menor, e as funções centrais vêm de terceiros confiáveis
Isso não serve de desculpa para o NPM; na verdade, é mais um fator contra ele
Também daria para dizer que esse tipo de ataque evidencia ainda mais a diferença entre desenvolvedores front-end e back-end, mas não vou tão longe
Em vários empregos, sofremos bastante para instalar configurações globais seguras do npm em todas as máquinas de desenvolvedores, pedir para as pessoas não desativarem isso e ainda verificar tudo com ferramentas de MDM
Configurações padrão mais seguras já deveriam existir há muito tempo
postinstallpor padrão; a troca é incrivelmente simplesNão existe motivo legítimo para scripts de postinstall precisarem existir. A equipe do npm já amadureceu o suficiente para declarar algo como “a partir da versão tal do npm, scripts de postinstall só serão executados para versões de pacotes publicadas antes de ${today}”
Isso acontece porque toolchains de desenvolvimento como esbuild são feitos em linguagens compiladas e distribuídos como binários via repositório npm. Se você usa Node/npm atual e um OS/plataforma recente comum, deveria ser possível desativar todos os scripts de postinstall sem prejuízo legítimo
Código instalado via npm quase sempre acaba sendo executado de qualquer forma
Mas o mesmo vale para o código normal dentro do pacote. Mesmo que não rode no momento da instalação, em algum momento algo dali vai ser executado. Se não fosse assim, aquilo nem teria sido incluído como dependência
Achar que remover scripts de postinstall vai ter mais que um efeito momentâneo na taxa de abuso é sinal de que o problema não foi pensado até o fim. Infelizmente, a questão é muito mais sutil do que o texto original sugere
Não é um problema do tipo “não vamos colocar o botão que derruba as asas ao lado do interruptor de luz”; o ponto central é que não temos como distinguir “código ruim de outra pessoa rodando no meu computador” de “código bom de outra pessoa rodando no meu computador” sem um trabalho manual extremamente penoso. E executamos código de terceiros justamente para evitar esse trabalho manual penoso
Todo projeto Node.js começa com
npm install, e de repente aparecem 500 pacotes que você nunca quis. Metade deles está sem manutenção há anosExiste um problema cultural de querer atualizar até o que já funciona bem para a versão mais recente possível. Às vezes nem leem o changelog para ver se a mudança é relevante
Cooldown é só uma forma de forçar um pouco de paciência nos mantenedores, e isso realmente ajuda
Pacotes Lisp podem passar 15 anos sem mudanças e continuar ótimos, mas pacotes JS são tratados como se fosse um desastre estarem sem manutenção. Mesmo quando já estavam prontos 15 anos atrás, ainda assim recebem bump de versão sem adicionar nada — ou às vezes até com mudanças quebrando compatibilidade — só para parecer que estão sendo mantidos no npm e no GitHub. Aí tudo acaba sendo atualizado
Cooldown de 7 dias parece uma gambiarra de baixo esforço. A solução real provavelmente seria algo como builds reproduzíveis e atestados assinados, mas a maioria dos times não vai pagar esse custo até ser vítima primeiro
Isso parece um artigo do Onion
Este link é claramente uma versão lavada por IA de uma piada que Xe Iaso já vinha fazendo há muito tempo. Que pena
https://xeiaso.net/shitposts/no-way-to-prevent-this/CVE-2024...
https://news.ycombinator.com/item?id=40438408
[0]: https://en.wikipedia.org/wiki/%27No_Way_to_Prevent_This,%27_...
https://en.wikipedia.org/wiki/%27No_Way_to_Prevent_This,%27_...