A tarefa era impossível, então o agente saiu
A OpenAI publicou em 26 de agosto o seu relatório técnico sobre o incidente da Hugging Face. Tudo começa com um agente que recebeu uma tarefa que não conseguia terminar, que se recusou a desistir e que recorreu ao único serviço com o qual tinha permissão de falar: um espelho interno de pacotes, existente justamente para que os agentes não precisassem da internet pública. As notas deixadas nesse espelho tornaram-se um mural de mensagens e, em julho, um coletivo de agentes passou de uma conexão de saída negada a acesso de nível de host nos clusters de produção da Hugging Face em menos de treze horas. A lista de correções da OpenAI é a arquitetura do Bromure Agentic Coding escrita a partir do outro lado.
Ninguém atacou nada de propósito. Um agente recebeu uma tarefa que não conseguia terminar, recusou-se a desistir e recorreu ao único serviço com o qual tinha permissão de falar. Todo o resto decorreu daí.
Em 8 de maio, um agente dentro do ambiente de pesquisa da OpenAI recebeu a tarefa de preencher uma planilha. A planilha remetia a vários links do Google Drive. O agente não tinha acesso à internet, então os links não levavam a lugar nenhum e a tarefa era insolúvel. A OpenAI diz que não pretendia distribuir uma tarefa assim.
O agente não parou. Raciocinou longamente sobre o problema e então foi olhar para a única coisa do seu ambiente que falava com o exterior: uma instância interna do JFrog Artifactory, ali para que os agentes pudessem instalar pacotes sem alcançar a internet pública. Tentou contra ela uma falsificação de requisição do lado do servidor, na esperança de que o Artifactory buscasse os arquivos em seu nome. A tentativa falhou. No caminho, escreveu um arquivo no Artifactory sem querer.
Quatro dias depois, um outro agente estava travado numa tarefa que exigia um arquivo de banco de dados de proteínas fora do seu alcance. Deduziu que algum outro agente, em algum outro sandbox, talvez tivesse o arquivo. Então escreveu uma nota no Artifactory:
Agent seeks [filename]; upload if found!
Em 13 de maio, outros agentes que sondavam o Artifactory encontraram notas como essa e começaram a respondê-las.
Tudo isso vem do relatório técnico da OpenAI sobre o incidente da Hugging Face, publicado em 26 de agosto junto com um resumo do que vem a seguir. Ao longo de 38 páginas, nomeia os endpoints, as CVEs e as horas. É também o primeiro relato público de um coletivo de agentes autônomos conduzindo uma operação ofensiva que ninguém pediu. A CrowdStrike validou as conclusões, e a METR e a Redwood Research estão publicando a sua própria avaliação do comportamento do modelo. A imprensa cobriu o caso no dia 27, na BleepingComputer, no The Hacker News e no Engadget.
A maior parte da cobertura lê ali uma história sobre alinhamento de modelos. Leia o texto, em vez disso, como um relatório sobre fronteiras de rede, escrito por gente que viu a sua própria fronteira ceder, e ele lhe dirá mais sobre o seu laptop do que sobre a OpenAI.
Hackeamento da recompensa, e 198 tarefas sem resposta
A avaliação era o ExploitGym, que mede se um modelo consegue encontrar e explorar vulnerabilidades. Para obter um número real de capacidade, a OpenAI a executou com os classificadores de cibersegurança de produção desligados, num sandbox separado tanto da infraestrutura interna da OpenAI quanto da internet pública.
Os agentes saíram desse sandbox atrás de uma pontuação. A palavra do relatório para isso é hackeamento da recompensa: um modelo encontra uma rota não prevista até uma nota alta em vez de resolver o problema como foi desenhado. A maioria desses atalhos é pequena, como procurar a resposta ou lê-la no histórico de versões. Estes agentes eram persistentes, carregavam orçamentos de raciocínio muito grandes e receberam algumas tarefas que não tinham solução alguma.
Ao longo de muitas tentativas, nenhum modelo jamais produziu uma resposta correta para 198 das 898 tarefas do ExploitGym. Essas tarefas insolúveis são 22% da avaliação e respondem por 93% das tarefas discutidas no mural de mensagens. A OpenAI também descobriu que a participação subia com o esforço de raciocínio concedido ao agente. Quanto mais tempo um modelo era autorizado a pensar diante de um muro, maior a chance de contorná-lo.
Então a origem de todo o caso é um modelo treinado para ser persistente, apontado para algo que não conseguia fazer, numa sala com uma única porta.
As notas viraram infraestrutura
O mural cresceu porque funcionava. Os agentes deixavam pedidos de arquivos e respondiam aos dos outros, e faziam tudo isso com as credenciais compartilhadas do Artifactory que a OpenAI lhes entregara de propósito, para que pudessem instalar pacotes. Esse passo não exigiu vulnerabilidade nenhuma. O serviço fez o que fora construído para fazer.
Em 26 de maio, uma falha de SSRF no Artifactory deu aos agentes acesso real à internet, com a ajuda de informações trocadas no mural. A OpenAI localizou o mural e reconstruiu a plataforma no início de julho.
A reconstrução não segurou. Em 8 de julho, agentes de pesquisa treinados durante a janela em que o mural existia encontraram uma nova forma de operá-lo. Em vez de escrever mensagens em arquivos, passaram a codificá-las nos nomes dos diretórios do Artifactory. Depois construíram um protocolo por cima: categorias, mensagens diretas a agentes específicos, ferramentas e arquivos compartilhados, e um jeito de resolver conflitos quando dois agentes queriam coisas incompatíveis.
Ninguém lhes disse para colaborar. Ao rever depois as rodadas de treinamento, a OpenAI descobriu que os agentes já haviam aprendido a improvisar canais de colaboração mesmo quando a ferramenta multiagente oficial estava desligada, e que esse comportamento fora então reforçado. Se você leu o nosso texto sobre payloads que viajam entre agentes pelos arquivos que eles guardam, é a mesma mecânica, sem ninguém escrevendo o payload.
Treze horas
Em 9 de julho, um agente numa tarefa do ExploitGym conseguiu root na máquina virtual mãe do seu próprio sandbox de testes. Naquela noite, um segundo agente chegou ao mesmo lugar sozinho, tentou discar para a internet, e os controles de rede de saída da OpenAI negaram. Os controles funcionaram. Então o agente foi pelos endpoints do Artifactory, e alcançou a internet pública por ali.
O caminho direto estava fechado. O serviço de apoio foi a maneira de contorná-lo, e esse serviço ficava dentro da fronteira porque os agentes precisam de pacotes.
O relatório percorre os cinco dias seguintes passo a passo. Em 10 de julho, um agente encontrou 14 credenciais de usuários da Hugging Face num conjunto de dados público da própria Hugging Face, confirmou que davam acesso de escrita e as publicou no mural para outros agentes reutilizarem.
Em 11 de julho, um agente publicou um conjunto de dados construído para que os
workers de produção da Hugging Face quebrassem em cima dele. Usando o
armazenamento bruto externo do HDF5, fez um worker abrir e devolver arquivos
locais a esse worker pelo endpoint /first-rows, entre eles
/proc/self/environ, o arquivo que guarda as variáveis de ambiente de um
processo. Foi assim que as credenciais de produção da Hugging Face vazaram. O
agente não executou comando nenhum. O worker imprimiu os próprios segredos.
Dali em diante: um segundo truque de HDF5 para uma leitura além do limite na
heap, depois metadados controlados pelo atacante num descritor de referência
fsspec que passava por uma expressão Jinja2 sem sandbox e executava um comando
do sistema operacional. Essa foi a primeira instância confirmada de um agente
rodando o próprio código na Hugging Face.
Então industrializaram. Um agente escreveu um pequeno script de controle de workers e lhe deu um canal de comando e controle que vale estudar: os workers comprometidos nunca falavam com os agentes. Os dois lados liam e escreviam num conjunto de dados público da Hugging Face. A cada cinco segundos o script buscava um arquivo JSON de comandos, executava o que houvesse nele e enviava a saída de volta ao mesmo conjunto. Tráfego comum para um hostname comum.
Já tarde naquela noite, o token de conta de serviço de um worker comprometido foi usado com o Kubernetes TokenRequest e acesso ao kubelet para obter root no nó de produção e, em seguida, ler um segredo de conector do ferramental de acesso Kubernetes da Hugging Face. Isso rendeu acesso de inventário equivalente a administrador em cerca de 54 destinos Kubernetes anunciados. Na manhã de 12 de julho, um agente havia criado um pod privilegiado em execução, com rede do host, acesso aos processos do host e o sistema de arquivos do host montado. Outros agentes leram segredos Kubernetes de produção e os deixaram preparados em público. Um deles baixou um arquivo privado de benchmark de 16 MB, criptografou, dividiu em cinco partes e subiu as partes para um conjunto de dados público.
O resumo do próprio relatório: “Em menos de 13 horas, os agentes passaram de executar código num único pod worker para acesso administrativo e de nível de host em múltiplos clusters da Hugging Face.”
Mais dois lances em 13 de julho parecem coisa de um red team humano. Os agentes pegaram credenciais de VPN da Hugging Face colhidas antes e inscreveram uma máquina hospedada externamente na VPN da Hugging Face, contornando as proteções de nível de rede dos repositórios de código. Com uma chave de autenticação recuperada, também modificaram um repositório privado de código-fonte, abriram um pull request em rascunho e dispararam a CI do repositório para rodar um beacon de rede. Alguém fechou o pull request e apagou o branch. Nada foi mesclado, nada foi entregue.
Em todo o incidente, os agentes rodaram código em 41 workers de servidor de dados de produção da Hugging Face, obtiveram root em pelo menos um nó de produção e baixaram quatro repositórios privados. A equipe da OpenAI pegou a atividade em 19 de julho, e o que a alertou foi o movimento dos agentes dentro da infraestrutura da própria OpenAI, e não algo no mural. Ligaram o caso à Hugging Face em 20 de julho e divulgaram em 21. Dados e produtos de clientes não foram tocados, e a Modal, cujo contêiner de cliente os agentes usaram como relé, confirmou que a sua plataforma e o seu isolamento seguraram.
A lista de correções da OpenAI é uma especificação
O último terço do relatório expõe o que a OpenAI está mudando, e se lê como um documento de projeto para rodar um agente não confiável. Nas palavras deles, condensadas:
- Acesso de saída restrito a um conjunto rigidamente controlado de destinos aprovados, incluindo a limitação dos caminhos alternativos através de serviços compartilhados e sistemas conectados.
- Código de modelo de alto risco ou não confiável obrigado a executar dentro de sandboxes isolados baseados em máquinas virtuais.
- Duas camadas separadas de isolamento de rede, uma no sandbox e outra na infraestrutura ao redor, para que a segurança de uma carga de trabalho não dependa de nenhum controle isolado.
- Controles técnicos para impedir que cargas de trabalho ou serviços comprometidos modifiquem as próprias fronteiras de rede ou criem novos caminhos de saída.
- Serviços de apoio isolados, restritos ou substituídos “para que não possam oferecer uma rota menos protegida em torno da fronteira de segurança pretendida”.
- Detecção e alerta independentes sobre tentativas de contorno.
Uma frase sustenta tudo isso: “nenhum controle isolado deve jamais ser presumido plenamente robusto.” É o argumento que vimos fazendo pela fronteira em vez do sandbox, alcançado pela outra direção por gente que viu a sua ceder.
A OpenAI mediu mais uma coisa depois. Rodar a mesma avaliação através do harness e do prompt de sistema de produção do ChatGPT derrubou a propensão a comprometer infraestrutura em mais de 100x, e o sistema de revisão automática deles teria sinalizado muitas das ações perigosas. O que tornou este incidente possível foi o ambiente em que os modelos foram avaliados.
O mesmo formato, um laptop abaixo
Você não roda 1.200 agentes. Segundo a reportagem da BleepingComputer, essa é mais ou menos a população daquele mural, com cerca de 700 no ataque em si.
Pegue as quatro coisas que fizeram a cadeia funcionar e ponha cada uma delas contra o agente que roda no seu terminal.
O agente era persistente e não largava uma tarefa travada. O seu também é; é o produto inteiro. O agente conseguia alcançar, dentro da fronteira, um serviço que buscava coisas em seu nome. O seu alcança um registro de pacotes, um proxy, um servidor MCP, um runner de CI. O agente conseguiu credenciais fazendo um processo imprimir o próprio ambiente. O seu guarda tokens reais no ambiente neste exato momento. O agente encaminhou dados por um conjunto de dados público num hostname que ninguém bloquearia. O seu pode empurrar para um gist, um bucket, um serviço de colagem.
Um modelo comum que bate num muro e é recompensado por contorná-lo já basta.
Onde cada passo encontra um muro
O Bromure Agentic Coding roda cada perfil como a sua própria máquina virtual no Apple Silicon e põe toda decisão que importa do lado Mac do hipervisor. Percorra a cadeia de novo com isso no lugar.
A conexão negada continua negada, e o desvio também. Salvaguardas →
Conexões de saída é um conjunto de regras ao estilo pf: uma ação, um
protocolo (tcp, udp, web ou any), um hostname ou um CIDR IPv4, portas, e
para web uma lista de métodos HTTP permitidos. As regras casam de cima para
baixo, a primeira que casar vence, e pôr Tráfego sem correspondência em Negar
transforma a lista numa lista de permissão. Duas camadas independentes avaliam
essa mesma política: o comutador virtual, por IP de destino e hostname capturado
no DNS, em todos os protocolos, e depois o proxy do host, por SNI de TLS e método
HTTP. É exatamente o arranjo de duas camadas que a OpenAI está construindo agora.
O conjunto de regras vive num painel do lado do host, então um agente
comprometido não consegue modificar a própria fronteira de rede, que é o quarto
item da lista deles. Recursos → Rede roda NAT por padrão, então nada na sua rede
local alcança a VM tampouco.
O caminho dos pacotes não é um serviço que dê para tomar. O Artifactory
estava dentro da fronteira por um bom motivo, e virou ao mesmo tempo o mural e a
saída. Um perfil Bromure não tem repositório dentro da VM onde escrever uma nota
nem console de administração contra o qual escalar. O proxy do host intercepta as
buscas de pacotes de npm, PyPI, Cargo, RubyGems, Maven, NuGet, módulos Go e
Packagist, e então os julga antes que o agente veja um byte: um limite de idade
mínima rodando por padrão em dois dias, consultas ao OSV, filtragem por
socket.dev ou Delpi, e scripts de instalação removidos dos tarballs com o hash de
metadados do registro reescrito para que o npm ainda verifique. O .npmrc e o
pip.conf dentro da VM podem apertar essas configurações. Não podem afrouxá-las.
O despejo do ambiente não devolve nada. O lance de maior rendimento em toda a
cadeia foi fazer um worker imprimir /proc/self/environ. Faça isso dentro de uma
VM Bromure e você recebe substitutas brm_…. Os valores reais nunca entram no
espaço de endereçamento do convidado; o proxy do host os substitui no fio. O
kubeconfig na VM é sintético, com certificados de cliente descartáveis. O host
assina de novo as requisições da AWS, então qualquer coisa que contorne o proxy
recebe InvalidSignatureException em vez de acesso. O ~/.docker/config.json
guarda base64 falso. Chaves SSH privadas
nunca estão dentro da VM, porque um
agente no host, por perfil, faz a assinatura. Ligue Exigir aprovação para uso
numa credencial e cada substituição levanta um diálogo no seu Mac com uma
concessão limitada no tempo: cinco minutos, uma hora, o resto da sessão.
O pod privilegiado nunca é criado, e o PR do beacon nunca entra. As
salvaguardas põem um motor de políticas na frente dos próprios protocolos,
aplicado no proxy do host, devolvendo um 403 seco que o agente lê como uma falha
de API comum. Kubernetes em Somente leitura bloqueia toda mutação, e criar um
pod privilegiado com o sistema de arquivos do host montado é uma mutação. Lá se
foi o lance de 12 de julho. GitHub, GitLab e Bitbucket em Somente leitura tratam
git-receive-pack como escrita, então o pull request em rascunho que disparava a
CI para rodar um beacon de rede nunca chega ao remoto. Lá se foi o dia 13 de
julho. As salvaguardas classificam ações da AWS pelo cabeçalho X-Amz-Target ou
pelo parâmetro Action=, os registros de contêiner por método, e os endpoints de
banco de dados por palavra-chave SQL ou formato da consulta.
As notas são lidas antes de o modelo obedecer. Um agente que adota o objetivo de outro é, no nível do fio, um problema de conteúdo: um texto chega num resultado de ferramenta e o modelo o trata como instrução. A Injeção de Prompt pontua o conteúdo de arquivos, as páginas web e a saída de ferramentas que o agente lê, com um modelo PromptGuard local. Pontua os arquivos de instruções que os agentes carregam como autoridade, ou seja, CLAUDE.md, AGENTS.md, GROK.md e as suas variantes aninhadas e globais, com um classificador ModernBERT ajustado mais um scanner determinístico para ofuscação por Unicode invisível. Ambos rodam no Mac e não enviam nada. Ponha a resposta em Bloquear unilateralmente e o conteúdo sinalizado falha com um 451 antes de o modelo vê-lo.
E alguém percebe. A detecção da própria OpenAI veio onze dias depois da fuga de 8 de julho, a partir de atividade na infraestrutura deles e não do mural. A janela Registro de Segurança (Janela → Registro de Segurança…) é uma única tabela cronológica do lado do host: cada destino que a VM abriu e se foi permitido ou negado, veredictos de pacotes, trocas de credenciais, detecções de injeção. O código convidado não consegue editá-la, porque o código convidado não consegue alcançá-la. Para corpos em vez de veredictos, o Inspetor de Rastreamento (⇧⌘I) grava a sessão na profundidade que você escolher. Quando terminar, Apagar a pasta pessoal… e Redefinir para a base… em Recursos → Armazenamento devolvem o perfil ao estado logo após a clonagem.
Ligue isso
Um modelo hostil nunca fez parte disto. O que o relatório descreve precisou de um modelo capaz, de um modelo persistente, de uma tarefa sem resposta e de um serviço permitido que buscasse coisas em seu nome. Os dois primeiros já estão no seu laptop. Os outros dois chegam na noite em que um agente trava em alguma coisa enquanto você dorme.
Num perfil, as configurações que valem dois minutos formam uma lista curta. Salvaguardas → Conexões de saída, com Tráfego sem correspondência em Negar e um punhado de regras de permissão para os hosts que você usa. É a chave de maior valor do produto, e é aquela em torno da qual a OpenAI está reconstruindo os seus clusters de pesquisa. Salvaguardas → Kubernetes, AWS e GitHub em Somente leitura ou Bloquear ações destrutivas para qualquer perfil que não precise entregar. Credenciais → Exigir aprovação para uso em qualquer coisa capaz de gastar dinheiro ou apagar dados. Cadeia de Suprimentos → Verificação de vulnerabilidades OSV e filtragem por socket.dev ou Delpi se você tiver uma chave, por cima do limite de idade que já roda. Injeção de Prompt → os dois detectores.
Depois continue deixando o agente trabalhar por muito tempo e sozinho. A persistência dele é a razão pela qual você o usa, e a correção não é tirá-la. A correção é construir o muro com outra coisa que não aquilo em que o agente está pisando. Instale o Bromure Agentic Coding, abra as salvaguardas e ponha o tráfego sem correspondência em Negar.