- Duas versões maliciosas do cliente HTTP axios, amplamente usado, foram publicadas no npm e, ao serem instaladas, distribuíam um trojan de acesso remoto (RAT)
- O invasor contornou o GitHub Actions por meio do roubo das credenciais da conta do mantenedor e fez upload manual dos pacotes maliciosos
- As versões maliciosas incluíam a falsa dependência
plain-crypto-js@4.2.1, que instalava o RAT via scriptpostinstalle apagava seus rastros - O RAT infectava macOS, Windows e Linux e se comunicava com o servidor C2 (
sfrclak.com:8000) para baixar payloads adicionais - npm e GitHub removeram rapidamente as versões maliciosas, mas o caso voltou a destacar a importância de reforçar a segurança da cadeia de suprimentos e a proteção de credenciais
Visão geral do ataque à cadeia de suprimentos do axios no npm
- Em 31 de março de 2026, duas versões maliciosas da biblioteca cliente HTTP axios, amplamente utilizada, (
axios@1.14.1,axios@0.30.4) foram publicadas no npm - O invasor roubou as credenciais npm de um dos principais mantenedores do axios, contornou o pipeline CI/CD do GitHub Actions e publicou manualmente os pacotes maliciosos
- Ambas as versões inseriram uma falsa dependência chamada
plain-crypto-js@4.2.1, e esse pacote instalava um trojan de acesso remoto (RAT) por meio de um scriptpostinstall - O RAT tinha como alvo macOS, Windows e Linux, e se comunicava com o servidor C2 (Command and Control) (
sfrclak.com:8000) para baixar um payload de segundo estágio - Após a instalação, o malware apagava o código malicioso e seus rastros, substituindo-os por um
package.jsonlimpo para evitar a detecção forense
Linha do tempo do ataque
- 30 de março, 05:57 UTC:
plain-crypto-js@4.2.0(versão legítima) publicado - 30 de março, 23:59 UTC:
plain-crypto-js@4.2.1(versão maliciosa) publicado, com adição do hookpostinstall - 31 de março, 00:21 UTC:
axios@1.14.1publicado, com inserção da dependência maliciosa - 31 de março, 01:00 UTC:
axios@0.30.4publicado, com a mesma dependência maliciosa - 31 de março, 03:15 UTC: o npm remove as duas versões maliciosas
- 31 de março, 04:26 UTC: o npm substitui
plain-crypto-jspor um stub de detentor de segurança (0.0.1-security.0)
Visão geral do axios
- O axios é o cliente HTTP mais amplamente usado no ecossistema JavaScript, utilizado tanto em Node.js quanto em navegadores
- Com mais de 300 milhões de downloads semanais, um único release malicioso já representa potencial de dano em larga escala
- Para desenvolvedores comuns, é difícil perceber a instalação de código malicioso durante um
npm install
Etapas do ataque
-
Etapa 1 — Comprometimento da conta do mantenedor
- O invasor comprometeu a conta npm
jasonsaaymane alterou o e-mail paraifstap@proton.me - Depois disso, publicou builds maliciosas em ambos os branches de release 1.x e 0.x
- Releases legítimos são publicados por meio do OIDC Trusted Publisher do GitHub Actions, mas
axios@1.14.1foi publicado manualmente, semgitHeade sem assinatura OIDC - A suspeita é que o invasor tenha usado um token de acesso npm de longa duração
- O invasor comprometeu a conta npm
-
Etapa 2 — Pré-distribuição da dependência maliciosa
plain-crypto-js@4.2.1foi publicado pela contanrwise@proton.me- O pacote se disfarçava de
crypto-js, usando a mesma descrição e a mesma URL de repositório - Incluía o hook
"postinstall": "node setup.js", executado automaticamente durante a instalação - Após o ataque,
package.mdera trocado porpackage.jsonpara preparar a remoção de evidências
-
Etapa 3 — Inserção da dependência no axios
plain-crypto-js@^4.2.1foi adicionada como dependência de runtime- Ela nunca era importada no código → dependência fantasma (phantom dependency)
- Era instalada automaticamente durante
npm install, acionando o scriptpostinstall
Análise do dropper RAT (setup.js)
-
Técnicas de ofuscação
- Strings eram armazenadas de forma criptografada no array
stq[]e descriptografadas por_trans_1(XOR) e_trans_2(Base64 + ordem reversa) - A URL de C2 era
http://sfrclak.com:8000/6202033 - As strings descriptografadas incluíam identificadores de SO (
win32,darwin), caminhos de arquivos e comandos de shell
- Strings eram armazenadas de forma criptografada no array
-
Payloads por plataforma
-
macOS
- Um AppleScript era gravado em
/tmpe executado comosascript - O binário RAT era baixado do C2, salvo em
/Library/Caches/com.apple.act.monde executado - O nome do arquivo se disfarçava como um daemon de sistema da Apple
- Um AppleScript era gravado em
-
Windows
- O caminho do PowerShell era localizado e o arquivo era copiado para
%PROGRAMDATA%\wt.exe - Um VBScript baixava e executava do C2 um RAT em PowerShell
- Arquivos temporários (
.vbs,.ps1) eram apagados após a execução
- O caminho do PowerShell era localizado e o arquivo era copiado para
-
Linux
curlbaixava/tmp/ld.py, que era executado comnohup python3- O arquivo
/tmp/ld.pypermanecia no sistema - Nas três plataformas, o corpo POST
packages.npm.org/product0~2era usado para se disfarçar como tráfego legítimo do npm
-
-
Autoexclusão e ocultação
setup.jsepackage.jsoneram apagadospackage.mdera trocado porpackage.jsonpara se disfarçar como pacote legítimo- Depois disso, nem
npm auditnem uma revisão manual conseguiam detectar o problema - Ainda assim, a própria existência de
node_modules/plain-crypto-js/é evidência de infecção
Validação de execução com o StepSecurity Harden-Runner
- O Harden-Runner registra em tempo real eventos de rede, processos e arquivos no GitHub Actions
- Ao instalar
axios@1.14.1, foram detectadas duas conexões com o C2 (curl,nohup)- A primeira ocorreu 2 segundos após o início do
npm install - A segunda ocorreu 36 segundos depois e continuou em execução como processo em segundo plano
- A primeira ocorreu 2 segundos após o início do
- A análise da árvore de processos mostrou que o processo
nohupficou órfão sob o PID 1 (init), confirmando execução persistente - Nos logs de eventos de arquivo,
package.jsonfoi sobrescrito duas vezes- Primeira vez: durante a instalação, com a versão maliciosa
- Segunda vez: 36 segundos depois, substituído por um stub limpo
Indicadores de comprometimento (IOC)
-
Pacotes npm maliciosos
- axios@1.14.1 · shasum: 2553649f232204966871cea80a5d0d6adc700ca
- axios@0.30.4 · shasum: d6f3f62fd3b9f5432f5782b62d8cfd5247d5ee71
- plain-crypto-js@4.2.1 · shasum: 07d889e2dadce6f3910dcbc253317d28ca61c766
-
Rede
- Domínio C2: sfrclak.com
- IP: 142.11.206.73
- URL:
http://sfrclak.com:8000/6202033
-
Caminhos de arquivo
- macOS:
/Library/Caches/com.apple.act.mond - Windows:
%PROGRAMDATA%\wt.exe - Linux:
/tmp/ld.py
- macOS:
-
Contas do invasor
jasonsaayman(mantenedor comprometido)nrwise(conta criada pelo invasor)
-
Versão segura
- axios@1.14.0 (legítima)
Como verificar o impacto e responder
- Verifique 1.14.1 / 0.30.4 com
npm list axiosou empackage-lock.json - Verifique se
node_modules/plain-crypto-jsexiste - Se houver arquivos RAT específicos do sistema operacional, considere o sistema totalmente comprometido
- Verifique nos logs de CI/CD se houve instalação dessas versões e, em caso positivo, troque todas as chaves secretas e tokens
Etapas de recuperação
- Fixe o axios em uma versão segura (1.14.0 ou 0.30.3)
- Apague a pasta
plain-crypto-jse reinstale comnpm install --ignore-scripts - Se forem encontrados rastros do RAT, reconstrua o sistema
- Faça rotação de todas as credenciais (AWS, SSH, CI/CD etc.)
- Revise o pipeline de CI/CD e substitua chaves secretas
- Use a opção
--ignore-scriptsem builds automáticos - Bloqueie o domínio/IP de C2 no firewall ou em
/etc/hosts
Recursos do StepSecurity Enterprise
-
Harden-Runner
- Aplica uma allowlist de tráfego de saída de rede no GitHub Actions
- Bloqueia tráfego anômalo e registra logs
- Pode bloquear preventivamente conexões com
sfrclak.com:8000
-
Dev Machine Guard
- Monitora em tempo real pacotes npm instalados em PCs de desenvolvedores
- Detecta imediatamente máquinas com
axios@1.14.1e0.30.4
-
npm Package Cooldown Check
- Aplica um período temporário de bloqueio de instalação a pacotes recém-publicados
- Pode detectar publicações maliciosas rápidas como
plain-crypto-js@4.2.1
-
Compromised Updates Check
- Bloqueia merge de PRs com base em um banco de dados em tempo real de pacotes maliciosos
axios@1.14.1eplain-crypto-js@4.2.1são registrados imediatamente
-
Package Search
- Pesquisa em toda a organização onde um pacote específico foi introduzido em PRs e repositórios
- Permite identificar imediatamente o alcance do impacto (repositórios, equipes, PRs)
-
AI Package Analyst
- Monitora o registro npm em tempo real e faz detecção comportamental de pacotes maliciosos
- Detectou ambas as versões maliciosas poucos minutos após a publicação
-
Threat Center Alert
- Fornece alertas de inteligência de ameaças com resumo do ataque, IOC e procedimentos de resposta
- Garante visibilidade em tempo real via integração com SIEM
Agradecimentos
- O mantenedor do axios e a comunidade responderam rapidamente por meio da GitHub issue #10604
- O GitHub suspendeu a conta comprometida e o npm removeu as versões maliciosas e aplicou o security holder
- A resposta coordenada entre mantenedores, GitHub e npm minimizou os danos para desenvolvedores do mundo todo
2 comentários
Eu nunca imaginei que um pacote desse porte pudesse ser comprometido, mas o axios está além do que eu imaginava.
Comentários do Hacker News
npm, bun, pnpm e uv agora oferecem suporte à configuração de idade mínima de lançamento de pacotes
Eu adicionei
ignore-scripts=trueao meu~/.npmrc, e só essa configuração já teria mitigado a vulnerabilidadebun e pnpm não executam scripts de lifecycle por padrão
Exemplos de configuração para cada gerenciador de pacotes:
exclude-newer = "7 days"min-release-age=7minimum-release-age=10080minimumReleaseAge = 604800Curiosamente, cada um usa uma unidade de tempo diferente
Se você usa agentes com LLM, essa configuração pode causar falhas, então é preciso adicionar instruções relacionadas em
AGENTS.mdouCLAUDE.mdtimeoutMinutesem vez detimeoutmin-release-age=7 # daystalvez não funcione de fato~/.yarnrc.ymlcomnpmMinimalAgeGate: "3d"Houve choque com a notícia de que o Axios foi exposto a um ataque à cadeia de suprimentos
Não havia código malicioso dentro do Axios em si, mas uma dependência falsa chamada
plain-crypto-js@4.2.1foi injetada para executar um script de postinstall que instalava um RAT (trojan de acesso remoto)Para usuários de pnpm ou bun, que exigem aprovação manual de scripts de postinstall, isso foi uma boa notícia
A alegação de que gerenciadores de pacotes são um experimento fracassado
Existem bibliotecas C de alta qualidade compostas por um único arquivo
.c, como o SQLite, e esse modelo evita problemas de transitive dependencyA maior parte da superfície de ataque surge dessas dependências indiretas
Até o OpenSSL está sendo reescrito por problemas de qualidade de código, e no ecossistema JS é difícil expandir a biblioteca padrão, o que levou à proliferação de polyfills
Em vez disso, surgiu a proposta de reforçar os critérios de qualidade em repositórios como o npm e permitir registro apenas a mantenedores responsáveis
Surgiu a piada de que o dia começa com a saudação autodepreciativa: “qual pacote do npm foi comprometido hoje?”
Para usuários de Linux, foi recomendado usar bwrap para isolar em sandbox toda a lógica de build de npm, pip, cargo, gradle etc.
O bwrap oferece um ambiente isolado como o Docker, mas sem precisar de imagens. O Flatpak também se baseia na mesma tecnologia
Em deploy de servidores, o importante é o hardening de containers, e o ponto central é tratar o ambiente de CI/CD como uma zona não confiável
Ao executar IA, seria bom usar a mesma sandbox
requiredentro do código para que ele já possa ser executadoAo ver esse problema de dependências se repetir, surgiu a preocupação de que o ecossistema Rust um dia passe pelo mesmo tipo de situação
É difícil inflar a biblioteca padrão, mas é necessário um sistema confiável de garantia de qualidade de pacotes
Com a ajuda de IA, esse trabalho extra se tornou viável, e houve até quem reconhecesse que isso já deveria estar sendo feito há muito tempo
Práticas essenciais para minimizar a exposição a ataques à cadeia de suprimentos no NPM
--frozen-lockfilejá oferecem proteção suficienteÀ pergunta “como evitar totalmente esse tipo de ataque?”,
surgiu a opinião de que seria bom migrar para o Qubes OS e separar completamente o gerenciador de senhas do ambiente de build
Isso foi comparado a EPIs de laboratório químico: ambientes de desenvolvimento também precisam de isolamento e proteção
O pip já começou a bloquear instalação fora de virtualenv, e espera-se que no futuro os gerenciadores de pacotes ofereçam uma opção para recusar execução fora de sandbox
pnpm e bun agora ignoram scripts de postinstall por padrão, mas o npm ainda os executa
É recomendável definir
ignore-scripts=trueem~/.npmrcO npm ainda registra 80 milhões de downloads semanais
Especula-se que o vazamento de credenciais neste incidente provavelmente tenha se originado no caso anterior do LiteLLM
Usar Python ou Node.js parece inseguro, mas a sensação é de que isso é na verdade um problema universal