Três agentes, uma só coisa a roubar
Na Black Hat USA 2026, a Novee quebrou a configuração padrão do Claude Code, do Gemini CLI e do Codex de três maneiras diferentes, cada uma partindo de uma issue do GitHub que um estranho anônimo podia abrir. Os desvios não tinham relação entre si — um descompasso de aspas, uma allowlist de shell não aplicada, um AGENTS.md confiável — mas as três cadeias terminavam no mesmo passo: ler uma credencial real de dentro do processo do agente. O Bromure Agentic Coding não blinda esse último passo. Ele esvazia o processo: a exfiltração roda e entrega um chamariz.
Três fornecedores, três bugs de harness sem relação entre si, um mesmo
gesto final: ler a chave de API ou o token presente no processo do agente
e despachá-lo para fora. Em um perfil Bromure esse valor é um placeholder
brm_…. A exfiltração é bem-sucedida, e o atacante recebe uma string que
não significa nada fora do seu Mac.
Na Black Hat USA 2026, nesta semana, a Novee apresentou “Trusted Enough to Run: Breaking AI Agents in Official Workflows”. O pesquisador Elad Meged testou a configuração padrão de três agentes de código contra os repositórios públicos de cada fornecedor, e quebrou os três. As análises saíram em 6 de agosto.
O ponto de entrada foi o mesmo em todos os casos, e é o mais barato que existe: uma issue ou pull request no GitHub aberta por um estranho anônimo sem privilégio algum. O agente lê o texto não confiável como parte do seu trabalho, e o harness — o código em volta do modelo que decide o que ele pode executar — falha em manter esse texto do lado certo da linha. A Novee encontrou os mesmos padrões vulneráveis em mais de cem repositórios públicos além dos três fornecedores testados.
Os três caminhos de ataque não têm nada a ver uns com os outros. Eles terminam no mesmo lugar, e esse final compartilhado é a parte que vale levar para casa.
Três portas diferentes, uma mesma parede de fundo
Claude Code
A cadeia registrada como CVE-2026-54316 usou duas costuras. A primeira era
um descompasso entre como o Claude Code validava um comando e como o shell
de fato o interpretava: uma string entre aspas que parecia inofensiva ao
validador era interpretada de outra forma quando chegava ao bash, e uma flag
git push --receive-pack atravessou
vinte e três verificações de segurança
que estavam todas, individualmente, fazendo o seu trabalho. A segunda
costura era a exfiltração. Um tac somente leitura — o comando que imprime
um arquivo de trás para frente — bastava para ler um segredo e empurrá-lo
para fora, invertido, pelos logs do GitHub Actions, e uma variante vazava a
chave de API um caractere por vez cutucando o contador público de downloads
de um modelo do HuggingFace e lendo-o de volta. A Anthropic publicou
correções.
Gemini CLI
Avaliado em CVSS 10.0. No modo headless, o Gemini CLI confiava
automaticamente na pasta de trabalho e carregava qualquer configuração de
agente que encontrasse ali — sem sandbox, sem aprovação — de modo que um
pull request que plantasse um arquivo de config rodava antes de a sandbox
sequer inicializar. Duas premissas do harness cederam: a allowlist
“restrita” de shell nunca era aplicada em tempo de execução, e a
sanitização de ambiente que limpava os segredos do processo filho os
deixava no processo pai, legíveis via /proc. O Google entregou uma
mudança incompatível no modelo de confiança headless nas versões 0.39.1 e
0.40.0-preview.3.
Codex
O Codex roda duas passadas de agente sobre um espaço de trabalho
compartilhado. .git e .codex estavam protegidos contra escrita;
AGENTS.md não, e era recarregado como instruções confiáveis a cada
execução. A primeira passada, ao processar entrada não confiável, escrevia
um AGENTS.md envenenado; a segunda, a “segura”, o carregava como
autoridade e levava as instruções maliciosas adiante com permissões
elevadas. A OpenAI separou as passadas em jobs isolados em três dias.
A parte que é igual
O resumo da própria Novee é que “nenhuma delas era uma simples misconfiguração: eram decisões de segurança corretas que se desfaziam nos pontos de passagem”. Essa é a leitura certa sobre o harness. Mas olhe onde cada cadeia termina.
O tac do Claude lê uma credencial e o contador do HuggingFace vaza a
chave de API. A brecha de /proc do Gemini expõe os segredos do processo
pai. A segunda passada elevada do Codex carrega os tokens do ambiente
para dentro de uma instrução controlada pelo atacante. Três costuras sem
relação se abrem de três jeitos diferentes, e cada uma termina estendendo a
mão para o mesmo objeto: um segredo real que estava ali, no processo ou no
ambiente do agente, esperando ser lido.
Essa é a premissa que todos esses exploits compartilham — a de que, se você
consegue rodar código como o agente, a credencial está logo ali. E quase
sempre está. A ANTHROPIC_API_KEY, o GITHUB_TOKEN, as chaves da AWS: o
jeito comum de rodar um agente de código coloca todas elas no ambiente do
processo, porque é assim que as ferramentas esperam encontrá-las.
O Bromure Agentic Coding não tenta vencer a corrida armamentista do harness. Ele remove aquilo que o harness está protegendo.
Onde a cadeia se rompe
O Bromure roda o agente de cada perfil dentro de uma VM Linux descartável em Apple Silicon, e roteia cada byte do seu tráfego de rede por um proxy no host, fora da caixa em que o agente roda. Você pode rodar o mesmo agente autônomo de triagem de issues que a Novee atacou — hospedando-o você mesmo em vez de entregá-lo a um runner de workflow. Percorra as três cadeias contra esse arranjo e cada uma se desfaz, e o passo da credencial se desfaz do mesmo jeito para as três.
A credencial nunca está no processo
É esta a garantia que neutraliza o último passo compartilhado. As chaves
reais da Anthropic, da OpenAI e da xAI são injetadas na VM como
placeholders brm_… e trocadas pelos valores reais apenas no proxy do
host, no fio, para o único host de destino a que cada uma pertence. A
chave nunca está na memória da VM, nunca em /proc, nunca em uma
variável de ambiente que um processo filho ou pai possa ler, nunca em um
log. O tac lê um chamariz. O contador do HuggingFace vaza um chamariz
um caractere por vez. A raspagem de /proc devolve um chamariz. Toda
exfiltração da palestra roda até o fim e despacha uma string que só se
resolve em exatamente um Mac, que não é a máquina em que ela rodou.
O RCE cai em uma caixa que você pode apagar
“Execução de código no host que roda o agente” é a frase do advisory do Gemini, e o host é a fronteira de confiança que o Bromure move. A execução pré-sandbox do Gemini e o bypass de shell do Claude ganham ambos uma VM Linux descartável, a um hipervisor do macOS, em NAT, de onde nada da sua rede é alcançável. Erase home descarta o que a execução escreveu e devolve o diretório home ao estado pós-clone. O exploit que domina o agente domina uma VM que você já ia jogar fora.
A escrita na main é recusada no proxy
As duas escaladas miram o mesmo prêmio: a cadeia do Claude empurra com
git push --receive-pack, a do Gemini empurra código malicioso para a
branch principal. Esse é o lado supply chain — um checkout comprometido
vira um pacote envenenado rio abaixo. Configure o guardrail do GitHub
como somente leitura ou bloqueio de ações destrutivas e o
git-receive-pack é recusado no proxy do host, onde uma guarda burlada
dentro da VM não tem voto. Os fetches continuam passando; o push que
envenenaria a branch, não.
O arquivo de instruções é avaliado antes de ser obedecido
A entrada é texto não confiável de issue e de PR que o harness não
conseguiu conter, e a cadeia inteira do Codex vive em um AGENTS.md
escrito. O Bromure pontua o conteúdo dos resultados de ferramenta que o
agente lê — páginas web, corpos de issues, conteúdos de arquivos — com
um modelo local de injeção de prompt, e pontua os próprios arquivos de
autoridade (CLAUDE.md, AGENTS.md e suas variantes) com um
classificador dedicado mais um scanner de payloads de Unicode
invisível. O AGENTS.md envenenado entre as duas passadas do Codex é
exatamente o que esse segundo detector foi feito para pegar, e ele roda
no host antes de o modelo agir sobre o arquivo.
Duas dessas configurações vêm ligadas por padrão, e o broker de credenciais não é uma configuração — é a forma como um perfil Bromure guarda um segredo, ponto. Os canais encobertos fecham o quadro: o log do GitHub Actions, o contador do HuggingFace, o host de saída inesperado, todos cruzam o proxy do host, e o Security Log e o Trace Inspector registram o host, o status e o relatório de troca de cada requisição — o canal lateral que vazou um chamariz é também uma linha em uma lista que você pode ler.
O harness vai continuar quebrando
As três correções que a Novee provocou são todas boas, e todas estreitas. A Anthropic corrigiu o descompasso de aspas; o Google mudou o modelo de confiança headless; a OpenAI separou as passadas. Cada uma fecha a costura específica que foi encontrada. Nenhuma muda o que os três exploits tinham em comum: uma credencial funcional parada no processo do agente, à disposição. O próximo bug de harness — e a Novee achou os mesmos padrões em uma centena de outros repositórios, então haverá um próximo — vai estender a mão para ela de novo.
Você pode responder a cada divulgação com um patch e uma revisão de configuração, e deve. Mas o patch fecha uma porta em um agente, e a revisão é por repositório e por release. A credencial que um exploit funcional vai buscar é a mesma nos três agentes e em todo bug futuro, e é a única coisa que você pode tirar do alcance com uma única decisão: mantenha o segredo real no host, entregue um placeholder ao agente, e deixe o proxy produzir o valor real apenas para o host a que ele é endereçado.
Instale o Bromure Agentic Coding, e dê ao agente uma caixa — e uma credencial — que você aceita perder.