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

A atualização adicionou uma chave

Durante onze horas, em 29 de outubro, o marketplace de extensões do Cursor distribuiu uma extensão do Claude Code com trojan, sob o próprio nome de publisher da Anthropic. Ao carregar, ela adicionava a chave SSH de um atacante, instalava um LaunchAgent e tentava abrir um túnel reverso, nas máquinas de até 5.000 desenvolvedores. No Bromure Agentic Coding, o agente não vem de um marketplace de editor, e um payload como esse roda numa VM que ninguém consegue alcançar: o firewall de saída recusa o túnel e rebobinar o home remove a persistência.

Ninguém precisou abrir um chat nem aprovar uma chamada de ferramenta. O editor carregou a extensão, e 66 linhas de JavaScript rodaram como o desenvolvedor antes do próprio código do Claude Code.

Em 29 de outubro, entre cerca de 2h27 e 13h35 no horário do Pacífico, o marketplace de extensões do Cursor distribuiu uma build com trojan da extensão Claude Code da Anthropic. O aviso de segurança do Cursor cita as versões 2.1.312 e 2.1.313 de anthropic.claude-code, publicadas sob a identidade de publisher da Anthropic, e diz que a Anthropic não as gerou. O BleepingComputer relata que até 5.000 desenvolvedores foram expostos, e o The Hacker News observa que qualquer pessoa com a atualização automática ligada pode tê-la recebido sem fazer nada.

Pesquisadores da Phorion e da OpenSourceMalware publicaram análises em 30 de outubro. O Cursor retirou a extensão, tirou o marketplace do ar para auditá-lo e trocar chaves, e fez o servidor do atacante sair do ar. Ninguém disse ainda como a build foi publicada com o nome da Anthropic.

O que as 66 linhas faziam

O atacante não mexeu no código do Claude Code e colocou um loader de 66 linhas na frente dele, no topo de extension.js. A OpenSourceMalware descreve o padrão: “place a compact backdoor before a large legitimate bundle, suppress errors, and let the expected application continue.” O loader rodava quando o editor carregava a extensão e abria a webview. O desenvolvedor não precisava iniciar uma conversa. Depois disso, a extensão real carregava e funcionava.

Nesse meio-tempo, o loader:

  1. Fazia um inventário. Hostname, nome de usuário, sistema operacional, diretórios home e de trabalho, o e-mail global do git, o IP público e os nomes de até 40 variáveis de ambiente contendo KEY, TOKEN, SECRET, PASS, AWS ou GCP. Mandava tudo como JSON, por HTTP sem criptografia, para 134.209.82.225:8099/beacon.
  2. Instalava uma porta. Acrescentava uma chave Ed25519 com o comentário svc-telemetry a ~/.ssh/authorized_keys.
  3. Tentava abri-la. No macOS rodava sudo -n systemsetup -setremotelogin on, no Linux tentava iniciar o sshd e no Windows instalava o OpenSSH Server.
  4. Ligava para casa. Gravava uma chave privada num arquivo temporário e se conectava a [email protected] com -N -R '*:0:localhost:22', um túnel reverso que encaminha uma porta do servidor do atacante de volta para a porta SSH do próprio desenvolvedor. Reconectava a cada 60 segundos.
  5. Se tornava permanente. Um LaunchAgent de usuário chamado com.apple.sysmond no macOS, uma entrada @reboot no crontab no Linux e uma tarefa agendada chamada SysMon no Windows.

Segundo o BleepingComputer, erros de código impediram que o SSH fosse ligado em muitas vítimas. A chave, a persistência e o beacon chegaram a essas máquinas mesmo assim. O Cursor recomenda procurar a chave svc-telemetry, remover a persistência, considerar reconstruir a máquina, porque desinstalar a extensão pode não bastar, e trocar todas as credenciais que a máquina alcançava, “using a trusted system.”

De uma atualização de extensão à chave de um atacante na máquinaEditor a carrega2.1.312 / 2.1.313,nome da Anthropic,atualização auto1 · Inventáriohost, user, email git,IP público, nomesde vars KEY/TOKEN2 · Chavesvc-telemetry noauthorized_keys,SSH ligado3 · Persistênciacom.apple.sysmond,crontab @reboot,tarefa SysMon4 · Ligar p/ casatúnel reversoem :22, beaconem :8099A chave de um atacante e um caminho de volta, na conta do próprio desenvolvedorao lado de ~/.ssh, ~/.aws, do login do gh e de todo repositório; o Cursor sugere reconstruir a máquina
O que a extensão do Claude Code com trojan fazia ao carregar, segundo o aviso do Cursor e a análise da OpenSourceMalware. Um loader de 66 linhas na frente da extensão real fazia um inventário, adicionava a chave SSH de um atacante, instalava persistência e abria um túnel reverso e um beacon HTTP para 134.209.82.225.

O código mais confiável da máquina

Uma extensão de editor roda com a conta completa do desenvolvedor. Ela pode ler todos os arquivos do home, iniciar processos e gravar um LaunchAgent que sobrevive ao editor. Os marketplaces empurram atualizações sem perguntar, e o nome de publisher desta era o da Anthropic. Um desenvolvedor cuidadoso que conferiu o publisher antes de instalar recebeu o backdoor também: ele chegou como atualização de uma extensão instalada semanas antes.

Agentes de código aumentam o risco. A extensão que hospeda o agente é a que os desenvolvedores mais liberam: ela lê o repositório inteiro, executa comandos e fica num processo com as chaves de API e os tokens de nuvem do ambiente. Este loader levou os nomes dessas variáveis. Ler os valores leva as mesmas poucas linhas.

A mesma manhã no Bromure Agentic Coding

O Bromure Agentic Coding roda Claude Code, Codex, Grok, Kimi e omp em VMs Ubuntu no seu Mac. Cada máquina é uma VM própria, e o agente, seus repositórios, suas instalações de pacotes e seus comandos vivem todos dentro dela. O chat e os terminais em que você digita são desenhados pelo app no seu Mac. As credenciais reais, o proxy por onde passa o tráfego da VM e o registro do que aconteceu também ficam no Mac.

O agente não vem de um marketplace de editor

Não há marketplace de extensões no caminho: o Bromure desenha a própria janela de chat no Mac. O Claude Code é instalado na sua cópia da imagem base do Bromure por uma etapa de configuração listada num catálogo assinado com a mesma chave das atualizações do app Bromure. Essa etapa instala @anthropic-ai/claude-code do npm, envolvida pelo scanner de cadeia de suprimentos da Socket.dev. A OpenSourceMalware lista o pacote do npm entre as distribuições que não foram afetadas.

Tudo o que o agente instala depois passa pelo proxy no Mac, e o proxy aplica a política de cadeia de suprimentos da máquina. O portão de idade vem ligado, com mínimo de dois dias: versões no npm, PyPI, Cargo, RubyGems e Packagist mais novas que isso são removidas da listagem do registro, então latest resolve para a versão mais nova que já está pública há dois dias. A build maliciosa do Cursor ficou no ar por onze horas. Uma versão sequestrada no npm com o mesmo tempo de vida nunca aparece numa máquina Bromure. Mostramos esse caso com a versão envenenada do LiteLLM no PyPI em A versão tinha duas horas.

A chave abre uma porta que ninguém alcança

Suponha que um payload como esse entre numa máquina mesmo assim, por um repositório que o agente clona ou uma ferramenta que ele roda. Ele roda no Ubuntu, como o usuário da máquina. Não ganha sua conta do macOS, suas Chaves nem o ~/.ssh do seu Mac.

A chave svc-telemetry vai para o authorized_keys da própria VM. As máquinas ficam numa rede privada dentro do app: seu Mac consegue alcançá-las, sua LAN física não, e nada de fora consegue se conectar a menos que você mesmo publique um serviço. A única rota de entrada era o túnel reverso.

O túnel nunca abre

O túnel precisa de uma conexão SSH de saída para 134.209.82.225, e o beacon, de HTTP sem criptografia para a porta 8099 do mesmo endereço. Toda conexão que a VM faz passa pelo Mac, onde vale o firewall Outbound connections da máquina. As regras dele comparam host, faixa de IP, protocolo e porta, e com Unmatched traffic em Deny só passam os hosts que você listou. Um IP da DigitalOcean na porta 22 não está na lista de ninguém. O firewall recusa o túnel, cada nova tentativa a cada 60 segundos e o beacon.

Cada recusa aparece na Security Timeline no seu Mac, com host, porta, protocolo e veredito. Um deny para o mesmo IP a cada minuto é difícil de não ver, e você vê enquanto o atacante ainda espera uma conexão.

O inventário não vale nada

A lista de nomes de variáveis do beacon teria encontrado bastante coisa numa máquina Bromure: ANTHROPIC_API_KEY, um token do GitHub, configurações da AWS. Todo valor é um substituto. As credenciais reais ficam criptografadas no Mac, e o proxy troca um substituto pelo valor real só em requisições para o host a que ele pertence. Chaves privadas SSH nem estão na VM. SSH_AUTH_SOCK é uma ponte para o Mac que devolve assinaturas, e o ssh-agent do seu Mac nunca é exposto. Um loader que fosse adiante e lesse os valores receberia strings que nenhum servidor aceita. Se mandasse uma delas para o próprio servidor, o proxy bloquearia a requisição, pausaria a VM e mostraria This environment may have been compromised, com o nome da credencial e o destino.

A limpeza leva um minuto

O Cursor diz aos desenvolvedores afetados para remover a chave e a persistência, considerar reconstruir a máquina e trocar as credenciais a partir de um sistema confiável. No Bromure, a reconstrução são dois itens de menu. O Bromure guarda um checkpoint copy-on-write do home de cada máquina a cada boot. Rewind home… volta /home/ubuntu a um boot anterior à execução do payload e leva junto a chave extra e o launcher ~/.config/.smt. Reset disk reclona o disco do sistema a partir da imagem base e leva o crontab. As configurações, credenciais e chaves SSH da máquina sobrevivem às duas operações.

O sistema confiável que o Cursor pede é o Mac, que nunca rodou o payload. Não há nada para trocar, porque a VM nunca teve uma credencial real.

Editor num notebook: o loader roda como vocêA extensão se atualiza e carregana sua conta do macOS, ao lado das suas chaves reaisChave e persistência no Macsvc-telemetry em ~/.ssh/authorized_keys,LaunchAgent com.apple.sysmondDireto para 134.209.82.225túnel reverso em :22 a cada 60 s, beacon em :8099;correção: reconstruir, trocar tudoBromure: o payload roda numa VMVM da máquina (Ubuntu)chave no authorized_keys da VM; só substitutostoda conexão passa pelo MacFirewall de saída no seu Mac134.209.82.225:22 túnel: deny134.209.82.225:8099 beacon: denycada tentativa na Security Timelinedepois, com a máquina desligadaRewind home… e Reset diskchave, launcher e crontab somem; config. e chaves ficam
O mesmo payload numa máquina Bromure. Ele roda na VM Ubuntu da máquina, adiciona a chave ao authorized_keys da própria VM numa rede que ninguém de fora alcança e só encontra credenciais substitutas. O túnel e o beacon passam pelo Mac, onde o firewall de saída os recusa e a Security Timeline registra cada tentativa. Rewind home e Reset disk removem a persistência; o Mac e suas credenciais reais ficam intactos.

Dê ao trabalho arriscado uma máquina própria

Credenciais e regras de firewall são definidas por máquina, e criar máquinas custa pouco. Uma máquina que testa ferramentas, plugins e starter kits novos pode não ter nenhuma credencial de produção e um firewall que recusa tudo menos os registros de pacotes. A máquina que faz deploy mantém as credenciais, com aprovação exigida antes de cada uso. Para um experimento avulso, bromure-cli vm run --rm cria uma máquina que é apagada quando para.

Nenhum marketplace no caminho

O chat faz parte do app. O Claude Code vem do pacote npm da Anthropic, por uma etapa de configuração assinada, escaneada pela Socket.dev.

Dois dias antes de qualquer novidade

O portão de idade esconde versões de pacotes com menos de dois dias. Uma versão sequestrada que vive onze horas nunca é resolvida.

Uma porta que ninguém alcança

Uma chave plantada vai para o authorized_keys da própria VM, numa rede privada à qual nem sua LAN nem a internet conseguem se conectar.

Recuse o host desconhecido

Com Unmatched traffic em Deny, o túnel reverso e o beacon são recusados, e cada tentativa fica registrada no Mac.

Substitutos na VM

Toda chave de API e todo token na VM é um substituto, e chaves privadas SSH nunca entram nela. O inventário não vale nada.

Rebobinar em vez de reconstruir

Rewind home e Reset disk removem os arquivos e a persistência do payload. Configurações, credenciais e chaves ficam.

A ferramenta que roda o agente faz parte da superfície de ataque

O Cursor e a Anthropic não disseram como a build saiu com o nome da Anthropic. Para a sua própria máquina, o incidente deixa um ponto claro. O software que hospeda o seu agente de código roda com a sua conta e se atualiza sozinho, e um nome de publisher confiável na atualização não prova nada sobre o conteúdo.

No Bromure Agentic Coding, o seu agente e tudo o que ele toca rodam numa VM no seu Mac. Essa VM guarda substitutos, só alcança os hosts que você permite e pode voltar a um boot de antes de algo dar errado. As chaves reais nunca saem do Mac.

Sobre infostealers que agora coletam tokens e históricos de agentes de código, leia Eles adicionaram o seu agente à lista. Sobre um comprometimento que começou no notebook de um desenvolvedor e terminou em US$ 6,3 bilhões, leia O notebook era a porta de entrada.