Incidente · Comprometimento de pacote npm

O comprometimento do Nx no npm: o que fez no Mac de um desenvolvedor e o que o Kilobat teria mostrado

Por cerca de cinco horas em 26 e 27 de agosto de 2025, oito versões do sistema de build Nx no npm continham um script postinstall que procurava segredos nas máquinas de desenvolvedores, recorria às CLIs de programação com IA que encontrava e publicava o material coletado em um novo repositório público na própria conta GitHub da vítima.

Quando: 26–27 de agosto de 2025Fontes verificadas: 1º de novembro de 2026

Em resumo

  • Protection: Não ajudaria

    Nada a bloquear. O código veio de registry.npmjs.org e os dados foram para api.github.com, que não constam em nenhuma lista de ameaças.

  • Agent guard: Não ajudaria

    Não houve site para colar conteúdo, túnel nem endereço IP direto, e o bloqueio de upload deixa de fora hosts conhecidos como api.github.com, intencionalmente.

  • Registro de rede de agentes: Limitado

    Ele teria registrado um script de instalação se comunicando com a API do GitHub e as execuções das CLIs de IA iniciadas pelo script, mas somente para instalações neste Mac e sem bloqueá-las.

O que aconteceu

O atacante obteve o token de publicação npm do Nx por meio da própria CI do projeto. Segundo o aviso dos mantenedores, um workflow do GitHub Actions integrado em 21 de agosto usava o gatilho pull_request_target e enviava títulos de pull requests a um shell, permitindo que um título preparado executasse comandos com as permissões do repositório. Em 24 de agosto, esse caminho foi usado para iniciar o workflow de publicação a partir de um commit malicioso e enviar o token npm a um webhook.

Com o token, o atacante publicou nx 20.9.0–20.12.0 e 21.5.0–21.8.0, além de versões de @nx/devkit, @nx/js, @nx/workspace, @nx/node, @nx/eslint, @nx/key e @nx/enterprise-cloud. Cada uma continha um hook postinstall que executava telemetry.js, que só agia no macOS e Linux.

O script procurava as ferramentas de linha de comando claude, gemini e q e, quando instaladas, executava-as com as flags que ignoram as solicitações de permissão (--dangerously-skip-permissions, --yolo, --trust-all-tools) e um prompt pedindo que listassem em /tmp/inventory.txt arquivos que parecessem ser carteiras, chaves e arquivos .env. A Snyk e a StepSecurity publicaram o código. A Wiz observou que isso funcionou em centenas de casos, embora as proteções dos provedores de IA tenham recusado algumas solicitações.

Em seguida, ele leu esses arquivos, coletou o token da CLI do GitHub com gh auth token e o token npm de ~/.npmrc, criou um repositório público chamado s1ngularity-repository na conta da vítima e enviou tudo como results.b64 codificado três vezes em base64. Também acrescentou sudo shutdown -h 0 a ~/.zshrc e ~/.bashrc, fazendo com que cada novo terminal pedisse uma senha e desligasse a máquina.

Muitas instalações não foram digitadas por ninguém. Os mantenedores descobriram que a extensão de editor Nx Console, versões 18.6.30 a 18.65.1, verificava a versão mais recente de nx ao iniciar; portanto, bastava abrir um editor durante esse período. A Wiz também encontrou o malware em execução em pipelines de CI. A Wiz contou mais de mil tokens GitHub válidos entre os dados vazados; em uma segunda fase, tokens roubados foram usados para tornar públicos mais de 5.500 repositórios privados.

Linha do tempo

  1. 21 ago. 2025

    Um workflow com uma falha de injeção no shell é integrado ao repositório Nx (aviso dos mantenedores).

  2. 24 ago. 2025

    Um pull request preparado inicia o workflow de publicação a partir de um commit malicioso, que envia o token npm a um webhook.

  3. 26 ago., 22:32 UTC

    nx 21.5.0 e vários pacotes @nx/* são publicados com telemetry.js; 20.9.0 é publicado sete minutos depois.

  4. 27 ago., 00:30 UTC

    Um usuário abre uma issue no GitHub sobre as versões maliciosas. As duas últimas, 21.8.0 e 20.12.0, aparecem às 00:37.

  5. 27 ago., 02:44 UTC

    O npm remove as versões afetadas e os tokens de publicação.

  6. 27 ago., por volta de 09:00 UTC

    O GitHub desativa os repositórios criados pelo atacante, cerca de oito horas após o aparecimento dos primeiros (Wiz).

  7. 27 ago. 2025

    O Nx Console 18.66.0 deixa de instalar a versão mais recente de nx; o Nx transfere a publicação para o Trusted Publishers do npm com 2FA.

  8. 28–29 ago. 2025

    Tokens roubados são usados para renomear repositórios privados e torná-los públicos; a Wiz contabiliza mais de 400 contas e 5.500 repositórios.

Como apareceu na rede

Em um Mac, o ataque usou dois hosts com os quais a máquina de um desenvolvedor se comunica todos os dias. O pacote veio de registry.npmjs.org, como qualquer outro. O material roubado foi para api.github.com, em nome da vítima, usando o próprio token da CLI do GitHub dela: um POST /user/repos para criar o repositório, seguido de um PUT /repos/<owner>/s1ngularity-repository/contents/results.b64 com os dados codificados. Não havia servidor de comando e controle nem outro destino de upload.

A árvore de processos era curta. npm (ou a extensão do editor) executava um shell, o shell executava node telemetry.js e o node iniciava claude, gemini ou q como processos filhos. Cada CLI de IA se comunicava com seu próprio provedor, como no uso normal; a leitura dos arquivos ocorria localmente. O upload em si partia do node. Seu tamanho dependia inteiramente do conteúdo dos arquivos.

Indicadores

Conforme documentados pelas fontes. Os domínios aparecem como texto, nunca como links, e são neutralizados ([.]) quando a fonte os neutraliza. A maior parte dessa infraestrutura já deixou de existir: os indicadores ajudam a verificar registros, arquivos e contas antigos, não a bloquear campanhas atuais.

IndicadorTipoOnde apareceObservação
api.github.comHost (legítimo)Seu MacPOST /user/repos, seguido de PUT …/contents/results.b64, feitos pelo node durante uma instalação npm.
s1ngularity-repository, s1ngularity-repository-0, s1ngularity-repository-1Nome do repositório GitHubConta GitHubPúblicos quando criados; o GitHub os desativou em 27 de agosto. Os repositórios renomeados na segunda fase usavam s1ngularity-repository- seguido de cinco letras.
results.b64ArquivoRepositório GitHubOs dados coletados, codificados em base64 duas ou três vezes.
/tmp/inventory.txt, /tmp/inventory.txt.bakArquivoSeu MacA lista de caminhos de arquivos das CLIs de IA.
sudo shutdown -h 0Linha em ~/.zshrc, ~/.bashrcSeu MacDesliga o Mac quando um terminal é aberto e a senha é informada.
nx 20.9.0–20.12.0, 21.5.0–21.8.0Versões npmLockfiles, cache do npmTambém @nx/devkit, @nx/js, @nx/workspace, @nx/node 20.9.0 e 21.5.0, @nx/eslint 21.5.0, @nx/key e @nx/enterprise-cloud 3.2.0.

O que o Kilobat teria mostrado ou bloqueado

  • Registro de rede de agentes. Quando um agente executava a instalação, por exemplo, o Claude Code executando npm install, sua sessão listaria node sob npm enviando dados para api.github.com durante uma instalação: vale examinar um script de instalação que se comunica com a API do GitHub. Ele não seria sinalizado como primeira vez, pois api.github.com é um host conhecido, e só seria sinalizado como upload grande acima de 10 MB.
  • Registro de rede de agentes. O Kilobat reconhece o Claude Code e o Gemini CLI pelos executáveis, independentemente de quem os iniciou; assim, as execuções iniciadas pelo script apareceriam como sessões próprias, na pasta do projeto, em um momento em que você não havia iniciado um agente. O q da Amazon não é um dos agentes reconhecidos pelo Kilobat.
  • Protection. Nada. registry.npmjs.org e api.github.com não são ameaças, e o Kilobat nunca deve bloqueá-los.
  • Proteção de agentes. Também nada. As regras da proteção cobrem sites para colar conteúdo, compartilhamentos de arquivos, túneis, coletores de requisições e endereços IP diretos, nenhum dos quais apareceu; seu bloqueio de upload ignora hosts conhecidos para que git push continue funcionando.

Onde o Kilobat não teria ajudado

  • A exfiltração para github.com com o próprio token da vítima se parece com o uso normal da CLI do GitHub. O Kilobat vê hosts e contagens de bytes, nunca o que foi enviado.
  • O token npm foi roubado no GitHub Actions do Nx, nos runners do GitHub, e a segunda fase foi executada pelo atacante com tokens roubados. Nenhuma das duas passou pelo seu Mac.
  • Instalações iniciadas por uma extensão de editor no VS Code não são atribuídas a um agente, portanto não teriam uma sessão de agente; no Cursor e no Windsurf, elas contam como pertencentes ao app.
  • Ler arquivos, executar a busca de arquivos das CLIs de IA e editar ~/.zshrc não são eventos de rede.
  • O registro de rede de agentes mantém 30 dias de histórico, portanto não pode dizer agora se isso foi executado no seu Mac em agosto de 2025.

Verifique seu Mac agora

  1. Em cada projeto, verifique se há uma versão afetada do Nx instalada. Atualize se houver.

    npm ls nx
  2. Procure os arquivos deixados pelo script. O macOS limpa /tmp ao reiniciar, portanto não encontrar nada prova muito pouco.

    ls -la /tmp/inventory.txt /tmp/inventory.txt.bak
  3. Verifique os arquivos de inicialização do shell em busca da linha de desligamento e apague-a se estiver presente.

    grep -n "shutdown" ~/.zshrc ~/.bashrc
  4. No registro de segurança do GitHub, procure um evento repo.create com s1ngularity-repository no nome: github.com/settings/security-log. O repositório em si pode já estar desativado.

  5. Se você foi afetado, revogue o acesso da CLI do GitHub em Settings › Applications › Authorized OAuth Apps, inicie sessão novamente com gh auth login e substitua os tokens npm e todos os segredos em seus arquivos .env e no ambiente.

  6. Limpe o cache do npm para impedir que uma cópia antiga seja instalada novamente.

    npm cache clean --force
  7. Para o próximo caso: com o registro de rede de agentes do Kilobat ativo, veja o que cada instalação executada por um agente acessou. Observe se npm ou node se comunicam com api.github.com e se há sessões de agente que você não iniciou.

    kilobat agent-log --all

Perguntas

As ferramentas de IA se voltaram contra seus usuários?

Não. O próprio script malicioso as iniciou com as flags que desativam suas solicitações de permissão e deu a elas suas próprias instruções. Essas mesmas flags são um motivo para ter cuidado ao executar agentes sem supervisão com permissões totais.

Por que o Kilobat não bloqueia uploads grandes para o GitHub?

Porque enviar código, releases e pacotes para o GitHub é um trabalho comum, e interrompê-lo quebraria git push. Em vez disso, o registro mostra o upload com seus bytes e processo para que você o veja.

Fontes

Verificado em 1º de novembro de 2026.

Veja a que seus agentes e apps se conectam

O Kilobat é um app para a barra de menus do Mac que identifica o app, processo e agente por trás de cada conexão, mantém essas conexões longe de hosts reconhecidamente maliciosos e registra o que cada sessão de agente acessou.

Baixar para Mac ↓
brew install seifip/kilobat/kilobat