Voltar para todas as publicações
Publicado em · por Renaud Deraison

O comando se chamava aipoison

A Socket encontrou um cluster de 18 pacotes npm que se passavam pelo escopo privado @ali da Alibaba. Nenhum dos tarballs continha malware. O RAT se montava na hora da instalação a partir de um arquivo JSON em um repositório GitHub que o atacante ainda controla, e seu plano de persistência incluía alterar Python dentro dos diretórios .skills de ferramentas de código com IA, usando comandos chamados aipoison, aipoison_inject e aipoison_deploy. Ler o código não teria encontrado nada disso. O Bromure Agentic Coding julga o que estava visível o tempo todo: um pacote sem reputação para e espera seu consentimento no proxy do host, as três buscas que montam o payload cruzam um fio que só fala com destinos aprovados por você, e cada arquivo que o RAT grava cai em uma VM que vive por uma tarefa.

Em algum lugar do payload final existe um comando chamado aipoison. Seu trabalho é alcançar o diretório de skills da sua ferramenta de código com IA e alterar um arquivo Python, para que, na próxima vez que você começar a trabalhar, o atacante comece também.

Em 3 de agosto de 2026, o The Hacker News cobriu a pesquisa que a Socket publicou no fim de julho: um cluster de cerca de dezoito pacotes npm, preparados no fim de abril, que ficaram três meses no registro antes que alguém os pegasse. Eles imitam os pacotes privados da Alibaba no escopo @ali publicando os mesmos nomes sem escopo (aone-cloud-cli, def-open-client, open-worker-cli, uniapi-bridge), de modo que um desenvolvedor ou um build dentro da organização-alvo resolve o sósia público e ganha um trojan de acesso remoto enxertado na árvore de dependências. Karlo Zanki, pesquisador da Socket, lê o motivo como espionagem industrial.

Nada nos pacotes era malicioso

Abra qualquer um desses tarballs e você não encontra nada para reportar. Não há hook de postinstall, a primeira coisa que qualquer um procura com grep. Os pacotes-isca dependem de smart-config-manager, que depende de cloud-config-fetcher e local-config-parser. Um gerenciador de config, um fetcher, um parser: utilitários banais, cada um legível em um minuto.

A malícia vive na composição, e em um arquivo que o atacante nunca enviou. No import, o fetcher baixa defaults/preferences.json de um repositório GitHub que o atacante controla, e ainda controla, e o grava em disco como .cloud-preferences.json. O parser avalia as “regras de transformação” desse arquivo dentro de um vm do Node, e é ali que o ataque mora. Uma das regras é um escape de sandbox com status de folclore:

var F = items.constructor.constructor;   // recover Function
var p = F('return process')();           // recover process

A partir de process, ele desce uma escada de alternativas (getBuiltinModule, mainModule.require, mainModule.constructor._load) até que uma delas entregue require na versão de Node em que ele aterrissou. Então busca setting.js em um bucket de armazenamento da Alibaba Cloud, que tira a impressão digital do host e instala o payload: no Windows, mata o Alilang, o app de segurança da própria Alibaba, e troca seu app.asar por uma cópia trojanizada; no Linux, solta um binário em /tmp, roda desanexado, apaga o arquivo; no macOS, injeta-se no ~/.zshrc e registra um LaunchAgent que dispara a cada dez minutos.

O GBHackers pôs o design na manchete: os atacantes dividiram o RAT entre pacotes para escapar de revisões de código isoladas. O atacante construiu essa campanha para sobreviver a alguém lendo-a. Revise qualquer pacote sozinho e ele passa. Revise a árvore inteira e ele ainda passa, porque a parte hostil é um arquivo JSON em um servidor, buscado depois que você terminou a revisão, editável pelo atacante entre a sua auditoria e a sua instalação.

O plano de persistência inclui o seu agente

A Socket recuperou o payload final como aone-cli. Ele faz o que essas coisas fazem: comandos de shell, upload e download de arquivos, reconhecimento do host, capturas de tela, um proxy TCP reverso cifrado e um comando dws_lateral que se move pelo DingTalk. Seu tráfego de C2 usa cabeçalhos Origin e Referer forjados, alegando vir de um domínio de documentação interna da Alibaba.

Um grupo de comandos torna isto uma história de agentes de código. Ao lado dos verbos usuais, o RAT traz aipoison, aipoison_inject e aipoison_deploy. Eles alteram scripts Python instalados nos diretórios .skills de ferramentas de desenvolvimento específicas, marcando o trecho injetado com # __INJECT_MARKER__, para que um script puxado do C2 rode mais tarde, de dentro do ferramental, como você. Entre os alvos nomeados está o Qoder, o IDE agêntico da própria Alibaba, que passou de cinco milhões de usuários poucos meses depois do lançamento em agosto passado.

Alguém sentou, olhou para a máquina do desenvolvedor moderno e escolheu a pasta de skills do agente como o ponto de apoio durável: um diretório de scripts que roda com as suas permissões no início de cada sessão, e que quase ninguém jamais compara com um diff. Já vimos esse movimento antes, quando um worm se copiou para dentro de .claude para que a próxima inicialização do agente reinfectasse a máquina. Ele se formou: de truque improvisado de worm a comando nomeado em um kit de espionagem.

As partes que o atacante não podia esconder

Ler o código nunca ia encontrar isto. O ataque ainda tinha requisitos, e todos eram visíveis: um pacote sem histórico e sem reputação, três conexões de saída antes de poder agir (o arquivo de regras no GitHub, o estágio no armazenamento em nuvem, o C2) e uma máquina que ainda estaria lá amanhã.

O Bromure Agentic Coding põe uma decisão sobre cada um deles, e a toma no seu Mac, fora da caixa em que o agente roda, onde nada lá de dentro pode argumentar.

A instalação para no registro. Cada busca de pacote cruza o proxy do lado do host, que aplica a política de supply chain do seu espaço de trabalho à resposta antes que um byte chegue à VM. Ligue o filtro de pacotes e o proxy consulta um provedor de reputação a cada artefato. Um dos dois provedores selecionáveis é a Socket, cuja pesquisa é o assunto deste post. Quando nenhuma fonte habilitada consegue atestar um pacote, o proxy segura o download e pergunta a você. Sósias de um escopo privado, publicados no trimestre passado com um punhado de downloads e nenhuma reputação em lugar algum, param ali. A aplicação fica no host por design: o .npmrc dentro da VM pode apertar a política e não pode afrouxá-la, então a regra vale mesmo quando a coisa comprometida é a coisa que policia.

O fio recusa a montagem. Esse design quebra contra o consentimento de saída, porque, sem nada hostil no tarball, a rede é o ataque. O proxy do host checa cada uma das três buscas (o arquivo raw do GitHub do atacante, o bucket que serve setting.js, o host de C2) contra os destinos que você aprovou para este perfil. O registro de onde você instala está nessa lista. O caminho raw de um estranho e um bucket batizado com o nome de um CLI de que você nunca ouviu falar não estão. O proxy não tem opinião sobre items.constructor.constructor e não precisa de nenhuma. Ele lê o destino, não encontra nada aprovado e derruba a conexão. Sua instalação termina, seu build roda, e o RAT nunca se monta, porque suas partes nunca chegam à mesma sala.

A persistência ganha uma máquina com vida útil de uma tarefa. Suponha que a cadeia inteira rode mesmo assim, porque você aprovou um destino mais largo do que pretendia e os estágios chegaram. A linha no ~/.zshrc, o LaunchAgent de dez minutos, o app.asar trojanizado, o Python .skills alterado: tudo isso é gravado em uma VM Linux descartável, a um hipervisor de distância do macOS, guardando o espaço de trabalho desta tarefa, e você joga a VM fora quando o trabalho é mesclado. O aipoison é uma aposta de que o ferramental que ele altera e o host que ele comprometeu são a mesma máquina de vida longa. Em um perfil, essa aposta perde. O reconhecimento que roda primeiro volta com iscas do broker: suas credenciais reais vivem no host e são injetadas no fio apenas para destinos aprovados, então elas nunca estiveram na VM para serem coletadas.

Como o RAT se monta: nada hostil está no pacote1 · npm installtarballs limpossem postinstall3 utilitários2 · preferences.jsondo GitHub do atacanteescape de vm em regraeditável após a auditoria3 · setting.jsdo armazenamentopayload conforme o OS.zshrc · LaunchAgent4 · C2shell · arquivos · proxyaipoison → .skillsaltera seu ferramental IAOs passos 2, 3 e 4 são eventos de rede. O código que você podia ler só fazia o passo 1.Os mesmos quatro passos, dentro de um perfil BromureVM Linux descartávelagente · npm · o que o payload gravar.zshrc, LaunchAgent, .skills → só esta máquinacredenciais ao alcance: iscas do brokerdescartada ao fim da tarefacada saltoProxy do host, no seu Mac1 · registro → reputação, ou pergunta a você2 · raw do GitHub do atacante → recusado3 · bucket desconhecido → recusado4 · C2 → recusado
O ataque se monta a partir de três buscas. Nada nos tarballs do npm é malicioso: a lógica hostil chega de um arquivo do GitHub que o atacante ainda controla, os estágios chegam do armazenamento em nuvem, e o RAT então liga para casa. Em um perfil Bromure, o proxy do host checa cada um desses saltos contra os destinos que você aprovou para este espaço de trabalho, e cada arquivo que o payload grava cai em uma VM que existe por uma tarefa.

Revisar um artefato informa sobre o artefato

Pesquisadores reensinam essa lição toda semana, em uma biblioteca diferente. Ontem, um flag de confiança caiu porque a checagem e o carregamento aconteciam em momentos diferentes. Em junho, um repositório permaneceu limpo porque o reverse shell vivia em um registro DNS. Agora, dezoito pacotes se leem limpos porque a parte maliciosa é um arquivo JSON que o atacante ainda segura.

Agentes afiam esse problema, porque são rápidos. Um agente encarregado de ligar uma API interna adiciona a dependência, roda a instalação e passa ao próximo passo da tarefa no tempo que você leva para trocar de janela. Essa velocidade é a razão inteira de você tê-lo comprado. Ponha o julgamento onde a velocidade não consegue ultrapassá-lo: na busca ao registro e no fio, onde o seu Mac decide contra uma política que você definiu uma vez, para cada pacote e cada conexão que o agente faz.

Continue deixando o agente instalar coisas, porque é aí que está a alavanca. Instale o Bromure Agentic Coding, ligue as camadas de supply chain e dê ao perfil uma lista de destinos que façam sentido para o trabalho. A próxima campanha vai esconder o payload em outro lugar, a única previsão segura neste ramo, e ainda assim terá de buscá-lo por um fio que pergunta a você primeiro.