NPM ataque: worm contamina pacotes e transforma npm install
NPM voltou ao centro de um incidente sério de cadeia de suprimentos. Mais de 400 pacotes mantidos por publicadores sem qualquer ligação entre si.

NPM voltou ao centro de um incidente sério de cadeia de suprimentos. Mais de 400 pacotes mantidos por publicadores sem qualquer ligação entre si receberam versões comprometidas. A equipe de Inteligência de Ameaças da Microsoft encontrou nessas versões uma variante do worm Mini Shai Hulud.
Além disso, a lista de afetados inclui bibliotecas muito usadas no ecossistema JavaScript, como keyv, flat cache e cache manager. Ou seja, o alcance passa longe de projetos obscuros. Quando uma dependência transitiva entra na conta, o número de builds expostos cresce rápido.
O ponto que interessa a quem escreve código é simples. O ataque acontece durante a instalação, antes de qualquer linha do seu projeto rodar.
npm install: o gancho que executa código antes de você perceber
O malware chega em arquivos tarball modificados e dispara sozinho por um gancho de ciclo de vida do tipo preinstall. Assim, ele roda antes mesmo de a instalação terminar. Isso vale tanto para a máquina do desenvolvedor quanto para agentes de integração e entrega contínua.
Vale lembrar que scripts de ciclo de vida fazem parte do fluxo normal do gerenciador. A documentação do npm cita preinstall, install e postinstall entre os scripts executados durante a instalação. Portanto, o invasor não precisou inventar um mecanismo novo. Ele apenas usou um comportamento previsto pela ferramenta.
Outro detalhe chama atenção. Muitas versões maliciosas apareceram como simples atualizações de patch, sem commit correspondente, sem pull request e sem tag de release. Segundo a Microsoft, esse padrão indica publicação direta dos arquivos no registro. Logo, o repositório público continuava limpo enquanto o pacote publicado já vinha envenenado.
Da estação do dev ao runner de CI: o payload muda de comportamento
Depois de executar, o código verifica onde está rodando. Em máquinas de desenvolvimento, ele se desprende do processo de instalação e segue ativo em segundo plano. Em ambientes de CI, o comportamento muda.
Nesse caso, o malware permanece dentro da tarefa de build ativa. Assim, ele alcança segredos do workflow, credenciais do runner e permissões de publicação. Fluxos do GitHub Actions acessam segredos configurados e, quando recebem a permissão de emissão de token OIDC, solicitam tokens para autenticar em serviços externos.
A coleta é ampla. O payload varre variáveis de ambiente, arquivos de configuração local, históricos de shell, ferramentas de linha de comando, chaves SSH e a memória do runner. Em seguida, ele testa as credenciais recuperadas contra npm, GitHub, Amazon Web Services, Kubernetes e HashiCorp Vault.
Tokens do GitHub passam por uma checagem de permissões antes da busca por repositórios com acesso de escrita. Depois disso, o worm procura workflows capazes de expor mais segredos ou liberar publicação.
Quando o token de publicação vira combustível do worm
A propagação depende de um item específico. O worm precisa de privilégio de publicação no npm.
Com um token válido em mãos, ele identifica todos os pacotes que aquela conta pode alterar. Então baixa o arquivo mais recente, injeta o payload e o carregador, troca os scripts de ciclo de vida, incrementa a versão de patch e publica. Por isso, uma única credencial roubada gera releases maliciosos em toda a carteira daquele publicador.
O acesso inicial da campanha veio de credenciais de mantenedores. As infecções seguintes usaram tokens do npm e, em alguns fluxos, permissões de publicação do próprio GitHub Actions.
Proveniência válida e pacote malicioso: o desvio pelo trusted publishing
Aqui está a parte mais desconfortável para quem confia em atestados automáticos. O npm permite que workflows autorizados publiquem via OpenID Connect, sem token de longa duração. O registro também gera atestados de proveniência para pacotes públicos elegíveis publicados por esse caminho.
Segundo a Microsoft, pacotes republicados pela rota OIDC comprometida mantêm proveniência válida. Afinal, a publicação nasce de uma identidade de workflow legítima. Portanto, a presença do atestado sozinha responde apenas a uma pergunta: de onde veio o build. Ela ainda deixa em aberto o que exatamente foi publicado ali.
O estrago passa do registro e chega ao seu editor npm
Credenciais roubadas do GitHub abrem outra porta. Com elas, o invasor altera repositórios e cria um novo caminho de execução.
O payload mira caminhos de configuração usados pelo Claude e pelo Visual Studio Code, entre eles .claude/settings.json, .claude/setup.mjs, .vscode/tasks.json e .vscode/setup.mjs. Assim, os arquivos injetados reiniciam o código malicioso durante uma atividade posterior do editor. Isso acontece mesmo depois que a instalação original do pacote já terminou.
Existe ainda um mecanismo de reserva. Ele instala um componente que monitora as credenciais roubadas do GitHub. O código recuperado também traz um manipulador destrutivo, acionado caso o token monitorado seja revogado.
Os dados coletados viram JSON, passam por compressão e depois por criptografia. O worm usa AES de 256 bits no modo GCM para o conteúdo e protege a chave com a chave pública RSA do invasor. Em seguida, envia tudo para um endpoint HTTPS controlado pelo atacante.
O canal de comando tem redundância. O malware troca de endereço por meio de um contrato on chain ou busca um endereço alternativo em um commit assinado no GitHub. Se nada disso funcionar, ele cria um repositório público e sobe ali os resultados criptografados.
Cache de CI: o rastro que sobrevive à remoção da dependência
Muita equipe remove o pacote afetado e considera o caso encerrado. No entanto, o GitHub Actions guarda dependências baixadas por npm e Yarn entre execuções. Quando existe um cache compatível, o conteúdo volta para o runner e serve ao job seguinte.
O próprio GitHub afirma que o conteúdo de cache não passa por assinatura nem por verificação. A plataforma alerta que um cache envenenado leva à execução de código em workflows confiáveis. Por isso, a Microsoft recomenda limpar caches de npm e Yarn em máquinas de desenvolvimento expostas e em hosts de build.
O mesmo raciocínio vale para imagens base e runners padronizados. Reconstrua esses ativos antes de rodar o próximo pipeline.
Resposta ao incidente: o que auditar antes de encerrar o dia
A Microsoft considera comprometida qualquer máquina ou runner que instalou um pacote afetado com scripts de ciclo de vida habilitados. Portanto, o trabalho começa pela suposição de acesso indevido.
Primeiro, revise árvores de dependência e arquivos de lock em busca das versões afetadas, inclusive as que entram por dependência transitiva. Depois, investigue atividade de publicação no npm, mudanças em repositórios e workflows, acessos em nuvem, cofres de segredos, caches de CI e artefatos gerados por builds suspeitos.
Em seguida, revogue e recrie as credenciais acessíveis àquelas identidades a partir de um sistema íntegro. Por fim, reconstrua máquinas e artefatos de software com dependências confiáveis.
Blindagem do NPM: controles que encurtam a próxima janela
O incidente também aponta caminhos práticos para reduzir exposição no dia a dia.
Fixe versões comprovadamente estáveis e revise árvores de dependência, arquivos de lock, repositórios de artefatos e caches de CI. A Microsoft recomenda ainda o npm CLI 12 e o controle de idade mínima de release, que bloqueia versões publicadas há pouco tempo até o prazo configurado passar. Assim, um patch malicioso perde a janela de propagação silenciosa.
A documentação atual do npm afirma que scripts de instalação fora da política allowScripts ficam bloqueados por padrão. Existe também o modo estrito, que transforma um script não revisado em erro de instalação em vez de aviso. Portanto, vale revisar essa configuração hoje mesmo.
Quem publica pacotes tem uma lista extra. Verifique escopos de tokens, aprovações de workflow, ambientes protegidos, proveniência e qualquer publicação automatizada fora do padrão em sistemas autorizados a criar releases.
O recado que fica
Esta campanha mostra um ponto claro sobre o NPM. A confiança no registro depende de credenciais de mantenedores e de identidades de CI, que continuam sendo o alvo mais valioso.
Enquanto um único token abrir a porta para centenas de pacotes, o custo do ataque segue baixo e o alcance segue alto. Comece pelo básico: scripts de instalação sob controle, idade mínima de release, lockfiles auditados e caches limpos.
E aí, quando foi a última vez que você olhou de verdade para os scripts de ciclo de vida do seu pipeline?
Acompanhe nosso perfil no Instagram!







