No dia 31 de março de 2026, entre 00:21 e por volta das 03:15 UTC, duas versões do axios estiveram publicadas no npm com uma dependência a mais no package.json: plain-crypto-js@4.2.1. Essa dependência não era usada em runtime. Ela existia só para o npm resolver, instalar e disparar um script postinstall que baixava e executava um RAT (Remote Access Trojan, malware que dá ao atacante acesso remoto e persistente à máquina do alvo) multiplataforma no ato do npm install. As versões comprometidas foram axios@1.14.1 e axios@0.30.4, publicadas a partir da conta do mantenedor principal, que tinha sido tomada por um ator ligado à Coreia do Norte.
O que esse caso mostra não é que o npm é inseguro. É onde a confiança no npm realmente mora. Quando o time instala axios, a decisão que ele está tomando não é “confio nessa biblioteca”. É “confio em quem publica ela, em todos os maintainers que tocam ela, em todas as dependências transitivas dela e nos scripts de install que qualquer uma delas vier a trazer”. Este post é sobre o que dá para aprender desse incidente em particular e quais defesas operacionais fazem diferença num time pequeno, sem virar teatro de segurança.
O que aconteceu, em ordem#
A cronologia importa porque ela explica por que tantos ambientes foram expostos sem ninguém perceber.
- Em 30 de março, o atacante publicou
plain-crypto-js@4.2.0, uma versão limpa que imitava o nome docrypto-jslegítimo. Ficou de molho. - No fim do mesmo dia, publicou
plain-crypto-js@4.2.1, agora compostinstallmalicioso. - Em 31 de março, às 00:21 UTC, publicou
axios@1.14.1a partir da conta comprometida do mantenedor. Cerca de 39 minutos depois, publicouaxios@0.30.4. - Os dois releases do axios traziam
"plain-crypto-js": "^4.2.1"nopackage.json. Na prática, qualquernpm installque resolvesse uma dessas versões puxava o payload. - Por volta das 03:15 UTC, o npm removeu as duas versões maliciosas do axios. A janela total ficou em cerca de três horas.
- A conta do mantenedor teve o e-mail trocado para um endereço controlado pelo atacante antes dos publishes, e o acesso veio de uma combinação de engenharia social com um RAT na máquina pessoal dele.
Três coisas merecem atenção nessa linha do tempo. A primeira é que o pacote malicioso transitivo foi plantado antes, pra parecer uma dependência comum. A segunda é que o vetor não foi typosquat: o pacote comprometido foi o axios oficial, pela conta oficial do mantenedor principal. A terceira é que três horas no npm são suficientes para atingir muita gente, porque pipelines de CI rodam o tempo todo e instalam dependências transitivas sem curadoria.
Por que ninguém viu a tempo#
Existe uma leitura confortável do incidente que diz “é só revisar suas dependências”. Ela não sobrevive ao detalhe técnico.
A dependência maliciosa não aparecia no código do axios. Nenhum arquivo .js do axios fazia require('plain-crypto-js'). Ela estava só no package.json da versão nova, e o payload não rodava quando o axios era usado em runtime. Rodava quando o npm install resolvia a árvore e executava o postinstall do pacote transitivo. Quem lê o código do axios não encontra o RAT. Quem lê o package.json do axios encontra uma dependência a mais com nome plausível.
Some a isso três hábitos que quase todo time tem:
^1.14.0nopackage.json, que aceita qualquer minor/patch novo automaticamente.- Ambientes que rodam
npm installem vez denpm ci, o que permite resolver uma versão mais nova mesmo com lockfile. - CI que roda scripts de install por padrão, sem
--ignore-scripts.
Com essas três coisas juntas, o atacante não precisa que o alvo faça absolutamente nada fora do fluxo normal. Basta publicar a versão nova, e a próxima build captura.
Onde a confiança no npm realmente mora#
Vale nomear isso, porque o nome muda o que o time decide monitorar.
Quando um projeto depende de axios, a superfície de confiança real envolve, no mínimo:
- a conta npm de cada mantenedor com direito de publicar
- o e-mail e o 2FA atrelados a essas contas
- o pipeline interno do próprio projeto para publicar no npm
- cada dependência direta declarada no
package.jsondele - cada dependência transitiva que entra recursivamente
- todo script
postinstall,preinstalleinstallque qualquer pacote na árvore rodar
Nenhum desses pontos aparece no import axios from 'axios'. Todos eles são assumidos como confiáveis por padrão. O caso de março de 2026 atacou dois deles ao mesmo tempo: a conta do mantenedor e uma dependência transitiva com postinstall.
O que times poderiam ter feito antes#
Essa é a parte útil. Nenhuma das defesas abaixo é exótica, e nenhuma delas depende de ferramenta cara. Elas só precisam estar ligadas de verdade.
| Defesa | O que ela trava | Custo prático |
|---|---|---|
npm ci em vez de npm install em CI | Resolver versão fora do lockfile | Nenhum, é o comportamento correto para builds reproduzíveis |
--ignore-scripts em CI | Executar postinstall, preinstall e install de dependências | Requer auditar pacotes que realmente precisam de script (raros) |
| Lockfile commitado e revisado em PR | Trocar dependência transitiva sem revisão | Precisa de hábito de olhar o diff do lockfile |
Versões pinadas (sem ^ e ~) nas dependências sensíveis | Upgrade automático silencioso | Mais PRs de bump, idealmente automatizados e revisados |
| Política de idade mínima do release (ex.: 7 dias) | Consumir uma versão comprometida nas primeiras horas | Algumas ferramentas de SCA (software composition analysis) oferecem isso nativamente |
npm overrides para forçar versão segura conhecida | Subir silenciosamente via dependência transitiva | Baixo, entra no package.json do projeto |
| 2FA forte e hardware key em contas npm de maintainers | Account takeover por roubo de credencial | Baixo para o time, alto retorno para o ecossistema |
A regra geral: quanto mais o pipeline depende de decisões automáticas do npm, mais superfície de ataque ele tem. Cada item da tabela acima reduz uma dessas decisões automáticas.
O que fazer agora, se você rodou alguma build naquele dia#
Se o seu time tem qualquer chance de ter resolvido axios@1.14.1 ou axios@0.30.4 entre 31 de março 00:21 UTC e cerca de 03:15 UTC, a resposta operacional razoável é esta:
- Buscar nos lockfiles e histórico de CI por
axios@1.14.1,axios@0.30.4ou qualquer ocorrência deplain-crypto-js. - Verificar, nas máquinas envolvidas, se existe ou existiu o diretório
node_modules/plain-crypto-js. A presença dele é sinal de execução do install. - Procurar conexões de saída para
sfrclak.comou142.11.206.73na porta8000em logs de rede das últimas semanas. - Em máquinas onde houver qualquer evidência, assumir comprometimento e rotacionar tokens do npm, chaves SSH, credenciais de cloud, secrets de CI e qualquer segredo acessível pelo usuário afetado.
- Voltar para versões seguras:
axios@1.14.0na linha 1.x eaxios@0.30.3na linha 0.x. - Opcionalmente, adicionar
"overrides": { "axios": "1.14.0" }nopackage.jsonenquanto o rollback se consolida.
Esse passo a passo é o mínimo defensável. Em ambientes sensíveis, reformatar a máquina do desenvolvedor afetado é a recomendação padrão, porque o payload era um RAT com persistência.
A lição geral sobre confiar no npm#
O caso do axios não é uma exceção bizarra. É um lembrete de que a confiança no npm é uma cadeia, não um selo. Mantenedor, conta, 2FA, máquina pessoal do mantenedor, dependências diretas, dependências transitivas e scripts de install: cada elo pode falhar sozinho e derrubar os outros.
O remédio também não é heroico. É operacional e um pouco chato: npm ci, --ignore-scripts no CI, lockfile revisado, dependências pinadas onde importa, overrides para conter surpresas transitivas, e uma janela de carência antes de adotar release novo. Essas cinco ou seis decisões, somadas, teriam reduzido drasticamente o raio de explosão do incidente para a maior parte dos times.
Se você só tem tempo para uma ação hoje, essa é a ação: troque npm install por npm ci --ignore-scripts no seu CI e revise o diff do lockfile no próximo PR. As duas coisas juntas já cortam a maior parte da superfície que o caso do axios explorou.
Referências#
- Post Mortem: axios npm supply chain compromise (axios/axios#10636)
- Mitigating the Axios npm supply chain compromise — Microsoft Security Blog
- North Korea-Nexus Threat Actor Compromises Widely Used Axios NPM Package — Google Cloud Threat Intelligence
- Axios npm Package Compromised: Supply Chain Attack Delivers Cross-Platform RAT — Snyk
- axios Compromised on npm — StepSecurity

Comentários
Os comentários usam Disqus e só são carregados se você clicar no botão abaixo.