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

O comando começava com npm install

Em 24 de agosto de 2026, a equipe CTRL da Cato Networks publicou uma campanha que compra resultados patrocinados no Google para “codex macos download”, leva desenvolvedores a uma página do Google Sites disfarçada de portal do Codex da OpenAI e pede que colem no Terminal um comando cuja primeira linha é um npm install real do Codex. Tudo depois dessa linha é base64. O Bromure Agentic Coding nunca manda ninguém procurar um agente de codificação: o comando de instalação é uma string fixa no catálogo de imagens do próprio Bromure, roda dentro de uma VM Linux descartável, as credenciais lá dentro são iscas e, com o tráfego de saída não correspondido negado, as três requisições do carregador nunca deixam a máquina.

Há dois anos a indústria constrói controles para o que um agente de codificação instala. Esta campanha recua um passo e envenena como você instala o agente de codificação. Esse passo não tem registro, não tem lockfile e não tem atestação de proveniência. Tem uma caixa de busca, uma página que parece certa e as suas próprias mãos no teclado.

Um desenvolvedor quer experimentar o Codex CLI da OpenAI no seu Mac, então digita codex macos download no Google. O primeiro resultado é patrocinado e fica acima do anúncio da própria OpenAI. Ele leva a um portal de download limpo, com o logotipo certo e a tipografia certa, hospedado em sites.google.com. A página diz: abra o Terminal, cole isto.

Ele cola. O comando começa com npm install e o nome do pacote está correto.

Em 24 de agosto, a equipe de pesquisa CTRL da Cato Networks publicou a análise dessa campanha, repercutida no mesmo dia pela Infosecurity Magazine, pelo SiliconANGLE e pela Techzine. A carga final é um ladrão de informações para macOS. É a entrega que merece a análise.

O Google hospedou a página. Outra pessoa hospedou a isca.

O Google Sites é um construtor de sites. Qualquer pessoa com uma conta ganha uma página num domínio do Google, e o certificado, o cadeado e a primeira metade da URL pertencem todos ao Google. Essa é a confiança alugada.

A página em si não contém nada. A Cato não encontrou nenhum código malicioso nela. A isca chega dentro de um iframe apontado para a infraestrutura do atacante, roteado, segundo a análise da Cato, por um proxy de conteúdo estático do Google, de modo que até o segundo salto parece o Google buscando alguma coisa. A Techzine nomeia dois dos hosts do iframe: bright-links[.]com e swiftsaverfin[.]com.

Essa separação compra duas coisas para os operadores. A página visível nunca muda, então nunca dispara um sistema de reputação nem é reavaliada, e eles trocam as cargas do outro lado do iframe quando quiserem. A Cato contou três conjuntos distintos de infraestrutura, com o terceiro reutilizando um host de iframe do primeiro.

O resto se lê como uma operação madura de fraude publicitária. As iscas ativas ficam sob um caminho ofuscado, /codexx/, enquanto /codex/ serve algo inofensivo. Os operadores fazem fingerprinting dos visitantes, e tudo que não é um alvo macOS plausível vê conteúdo benigno, que é a resposta deles a pesquisadores e sandboxes. Os domínios rotacionam. As URLs de carga variam.

A primeira linha era de verdade

O ClickFix não serve um arquivo para você. Ele dá uma instrução e deixa que você mesmo carregue a carga através da fronteira. Como diz a Techzine, “nenhum arquivo é baixado que uma solução de antivírus poderia bloquear”.

O comando colado começa com uma string npm install de aparência legítima para o Codex. Esse é o truque inteiro. Um desenvolvedor prestes a instalar uma CLI Node vê npm install, vê o nome do pacote que procurou, e o cérebro dele arquiva a linha como correta. O blob base64 que vem depois está a um operador de shell de distância, na mesma linha, além da dobra da caixa de cópia. Você não lê a segunda metade de um comando cuja primeira metade é o comando que você esperava.

Decodificado, ele busca um script remoto e o canaliza para o zsh. Seguem três estágios.

O estágio um é um script shell inchado com código morto e variáveis não usadas, envolvendo um blob codificado que acaba entregue ao eval. O enchimento existe para derrotar a correspondência de padrões e para fazer o humano que folheia o arquivo desistir.

O estágio dois emite um sinal de volta para o atacante com um parâmetro event=pasted antes de fazer qualquer outra coisa. Isso é um recibo de entrega. Alguém do outro lado está medindo a taxa de colagem das suas páginas de destino, do jeito que um profissional de marketing mede conversões.

O estágio três baixa o binário para /tmp/helper, roda xattr -c para remover o atributo de quarentena que o macOS anexa a tudo que chegou da rede, o que suprime o aviso do Gatekeeper, marca o arquivo como executável e o dispara. O binário é um Mach-O universal, então roda tanto em Intel quanto em Apple Silicon.

A Cato observa que os operadores ainda estão desenvolvendo o carregador. Amostras mais antigas usavam base64 com compressão; as mais novas usam contêineres gzip cifrados em AES cuja chave é remontada a partir de variáveis espalhadas pelo script.

Para a carga final, a Cato liga o framework de entrega ao Atomic macOS Stealer: a estrutura da URL do carregador, o formato da requisição de telemetria, o caminho de preparo /tmp/helper, a remoção do xattr, as URLs de carga com tema de atualização. Eles chamam a sobreposição de forte e consistente e param antes de nomear o binário, o que é a decisão certa e vale manter quando você repete a história.

Entrega: tudo o que a vítima vêcodex macos downloadresultado patrocinado,acima do anúncio da OpenAIsites.google.comsósia do portal Codex,sem código malicioso próprioiframe: a isca de verdadebright-links[.]comswiftsaverfin[.]com“Terminal:cole isto”sem downloadA única linha que o desenvolvedor lênpm install ... codex ...; base64 -d ... | zshExecução: três estágios, três requisições de saída1 · carregadorscript shell inchado comcódigo morto e vars não usadaseval "$blob"2 · recibobaliza de telemetria?event=pasteda métrica de conversão deles3 · carga útil/tmp/helperxattr -c ; chmod +xMach-O universal
A cadeia da caixa de busca até o binário em execução. Nenhum exploit em lugar nenhum dela: um anúncio patrocinado, uma página hospedada pelo Google que não contém nada, um iframe que contém tudo, e um humano que carrega a carga através da fronteira ao colá-la. O único comando que a vítima chega a ver começa com uma linha npm install real para o Codex; o base64 que vem depois busca o estágio um. A baliza event=pasted do estágio dois é o recibo de entrega do próprio operador.

O passo acima dos scanners

Alinhe os controles que a indústria passou dois anos construindo para agentes de codificação. Varredura de reputação de registro. Lockfiles e hashes de integridade. Proveniência de build e atestação. SBOMs. Portões de idade mínima para novas versões de pacotes. Análise estática de código gerado. Todos funcionam, e todos partem da mesma premissa: o desenvolvedor já tem uma cadeia de ferramentas funcionando, e o risco está rio abaixo, no que ele faz com ela.

Esta campanha fica rio acima de tudo isso. A falsificação aqui é o próprio agente, e ela chega antes de qualquer registro, antes de qualquer lockfile, num comando que o desenvolvedor digita com as próprias mãos no próprio terminal. Um scanner não tem artefato nenhum para pontuar, porque o artefato é uma frase numa página web.

O direcionamento é a outra metade da economia. Quem dá lance em codex macos download está comprando a máquina de uma pessoa que está, naquele exato momento, montando um agente de codificação: uma máquina que dentro de uma hora vai conter um token de API, uma chave SSH, um arquivo ~/.aws/credentials e um PAT do GitHub, tudo aquilo que um ladrão de informações sabe encontrar. O momento da instalação é a hora mais barata de estar lá.

Já cobrimos o inverso disso: com FakeGit e AgentBaiting, é o agente que faz a busca e entrega ao humano os passos de instalação. Aqui é o humano que busca. Os dois funcionam porque descobrir-e-colar é como o software é instalado, e nenhum scanner fica em qualquer uma das pontas desse laço.

De onde vem o comando de instalação

O Bromure Agentic Coding não tem esse laço, e a razão está na origem do agente.

Você não sai procurando um agente de codificação. O Codex é um interruptor no painel Agents de um perfil, ao lado do Claude Code e do Grok Build. Ligue-o, escolha como ele se autentica, e o agente está lá na sessão seguinte, rodando numa aba do kitty dentro da VM do perfil.

Atrás desse interruptor há uma string fixa. O Bromure provisiona sua imagem base a partir do próprio catálogo, e a entrada do Codex é uma linha:

npx --yes @socketsecurity/cli npm install -g --silent @openai/codex

O Claude Code é @anthropic-ai/claude-code no mesmo padrão, o Kimi Code é @moonshot-ai/kimi-code. Os nomes dos pacotes são compilados no aplicativo, não descobertos. O registro é registry.npmjs.org, não o host que um iframe indicar. A instalação é embrulhada na CLI do socket.dev, e a requisição sai pelo proxy MITM do host, onde valem as políticas de Supply Chain do perfil: o portão de idade de dois dias que vem ligado por padrão, mais as consultas OSV, a filtragem por socket.dev ou Delpi, e a remoção de scripts de instalação que você pode ativar.

Esse caminho não tem resultado de busca e não tem página a imitar. O canal que o atacante pagou para envenenar está ausente do fluxo de trabalho, e ausente não é um controle que você precise lembrar de operar.

Instalar do jeito comumquem nomeia o artefato?quem venceu o leilão de anúnciosquem o serve?um iframe numa página sósiao que executa?o que vier depois da primeira linhaonde?seu Mac, sua conta de usuário, junto a~/.ssh · ~/.aws · ~/.git-credentialsGatekeeper silenciado por xattr -cQuatro perguntas em aberto, respondidas por um estranho.Ativar num perfil Bromurequem nomeia o artefato?@openai/codex, do catálogo de imagensquem o serve?registry.npmjs.org, via o proxy do hosto que executa?um comando compilado, sem texto livreonde?uma VM Linux descartável, criada antesda busca — sem chaves lá dentro,credenciais são iscas, saída é policiadaAs mesmas quatro perguntas, já respondidas.
Duas formas de adquirir um agente de codificação. À esquerda, o passo de aquisição é uma caixa de busca e um botão de copiar: o nome do artefato, o host que o serve e o comando que o instala são todos escolhidos por quem venceu o leilão de anúncios, e o resultado roda no Mac que guarda as chaves do desenvolvedor. À direita, o nome do artefato é compilado no aplicativo, o registro é fixo, a requisição é filtrada no proxy do host, e a instalação roda dentro de uma VM descartável construída antes de tudo isso começar.

Agora cole assim mesmo

A arquitetura tem que sobreviver ao dia em que alguém a ignora. Pegue a campanha, dê a vitória a ela, e leve-a por um perfil: alguém encontra o portal falso, copia o comando e o cola no terminal em que faz trabalho com agentes, que no Bromure Agentic Coding é uma aba do kitty dentro da VM.

O binário não roda. Um Mach-O universal é um executável macOS. O convidado é Ubuntu. xattr não é um comando Linux, e /tmp/helper é um caminho num disco de sistema que existe para ser descartado. Recursos → Armazenamento te dá Apagar a pasta pessoal… para /home/ubuntu e Redefinir para a base… para reclonar o disco de sistema do workspace a partir da imagem base compartilhada e somente leitura.

As três requisições não saem. Cada estágio dessa cadeia precisa da rede: a URL decodificada em base64 que puxa o estágio um, a baliza event=pasted e o download da carga. Guardrails → Conexões de saída é uma tabela de regras no estilo pf: ação, protocolo (tcp, udp, web, any), host ou CIDR, portas, e para web uma lista de métodos HTTP, avaliadas de cima para baixo, vencendo a primeira correspondência, com Tráfego não correspondido em Permitir ou Negar. Coloque em Negar e liste os hosts de que seu trabalho precisa. bright-links.com não é um deles. O Bromure aplica a tabela do lado do host, no switch virtual e no proxy, então nada que o convidado faça com o próprio ambiente muda a resposta.

O estágio dois é o que vale a pena examinar com calma. event=pasted é a métrica de conversão do operador, o ping que diz a ele que uma página de destino está funcionando, e quão bem. Quando essa requisição morre no host, ele não recebe um relatório de infecção que falhou. Ele recebe silêncio, o que se lê como uma impressão de anúncio que nunca converteu.

O roubo devolve marcadores de posição. Um ladrão da classe do Atomic vai atrás de dados de navegador, carteiras e, numa máquina de desenvolvedor, credenciais. Num perfil Bromure, os valores reais nunca entram na VM. Chaves de API genéricas são falsificações brm_… exportadas como variáveis de ambiente e trocadas no fio pelo proxy do host. O kubeconfig é sintético, com certificados de cliente descartáveis. As requisições AWS são reassinadas do lado do host, de modo que qualquer coisa que contorne o proxy recebe InvalidSignatureException. O ~/.docker/config.json guarda um blob base64 falso. Chaves SSH privadas não estão lá para serem lidas: nunca estiveram. Ligue Exigir aprovação para usar por credencial e cada troca vira um diálogo do lado do host com uma concessão limitada no tempo: cinco minutos, uma hora, o resto da sessão. Um perfil compartilha no máximo oito pastas que você escolheu, então o resto do Mac não está a uma caminhada de diretórios de distância.

A correlação já está na sua tela. A própria conclusão da Cato é que nenhum estágio isolado desta campanha a expõe; detectá-la exigiu correlacionar juntos a entrega por busca patrocinada, o conteúdo web embutido, a execução no Terminal e a atividade de saída. Isso é um problema difícil quando suas evidências estão num navegador, num shell e num capturador de rede. Num perfil, é uma janela só: o Log de Segurança (Janela → Log de Segurança…) é uma única tabela cronológica, do lado do host, de vereditos de pacotes, decisões de firewall, trocas de credenciais e detecções de injeção de prompt. Código convidado não pode editá-la, porque código convidado não consegue alcançá-la.

Ligue isso

O portão de idade vem ligado por padrão em dois dias. As outras camadas são configurações, e valem dois minutos: Guardrails → Conexões de saída, com Tráfego não correspondido em Negar e uma lista de permissões para os hosts de que seu trabalho precisa. Supply Chain → Verificação de vulnerabilidades OSV, mais a filtragem por socket.dev ou Delpi se você tiver uma chave, e a remoção de scripts de instalação. Credenciais → Exigir aprovação para usar em tudo que possa gastar dinheiro ou apagar dados. Depois deixe a janela do Log de Segurança aberta num segundo monitor por uma semana e veja com quem os seus builds conversam.

Resultados de busca patrocinados vão continuar sendo a porta da frente, e construtores de sites em domínios confiáveis vão continuar hospedando a varanda. O Google vai derrubar essas páginas e outras três vão subir, porque a economia é de alguns dólares por clique contra uma estação de trabalho de desenvolvedor com credenciais de nuvem dentro. Instale o Bromure Agentic Coding, habilite seus agentes pelo editor de perfis em vez de uma página de download, e deixe o próximo comando colado aterrissar numa máquina que foi construída para ser jogada fora.