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

Porque o Bromure Agentic Coding não é uma sandbox

Uma sandbox pede ao programador que abdique da velocidade que torna um agente de codificação digno de ser usado — pré-aprovar cada dependência, manter uma lista de domínios permitidos, nunca tocar num pacote que a organização não tenha avaliado. Por isso os programadores desligam-na. O Bromure Agentic Coding recusa essa troca. Não restringe o que o agente faz; traça uma única linha rígida no hypervisor e deixa-o fazer tudo do lado de dentro. Esta é a defesa fundacional de por que uma fronteira vence uma sandbox, e as três garantias que a fronteira torna verdadeiras: nenhuma credencial para roubar, tokens amplos estreitados no fio, e ataques à cadeia de fornecimento travados antes de o tarball aterrar — mais a quarta que a linha agora torna verdadeira: injeções de prompt apanhadas no conteúdo que o agente lê, antes de o modelo lhes obedecer.

Uma sandbox oferece uma troca: abdique de parte do que torna um agente de codificação útil, e em troca ela mantê-lo-á seguro. Os programadores recusam essa troca todas as vezes — desligam a sandbox, ou nunca a ligam — e fazem bem. A função de um agente é mover-se depressa por território confuso e não avaliado. O Bromure Agentic Coding não restringe isso. Traça uma única linha rígida, no hypervisor, e deixa-o fazer tudo o que quiser do lado de dentro dela.

Um post fundacional — escrito uma vez, para os restantes apontarem para ele. Não sobre um incidente. Sobre por que construímos o Bromure Agentic Coding da forma que construímos, e por que «é uma sandbox» é a descrição que continuamos a corrigir.

Um programador não é um administrador de sistemas.

A razão para pôr um agente de codificação na sua máquina é a velocidade — a do tipo concreto: puxar um pacote que ninguém na sua empresa avaliou, às onze da noite, para ver se uma ideia se aguenta. Experimentar a biblioteca, correr o seu exemplo, deitá-la fora se não encaixar. Isso não é um defeito a disciplinar para fora das pessoas. É o fluxo de trabalho, e a própria razão por que vale a pena ter o agente.

Por isso qualquer modelo que o obrigue a pré-aprovar cada dependência, ou que obrigue alguém a manter uma lista de domínios que o agente pode alcançar, está em guerra com aquilo que protege. Atrasa a única atividade que foi implantado para permitir — e um controlo que atrapalha a entrega tem exatamente um destino: é desligado. Um controlo que um programador desliga para conseguir trabalhar nunca foi um controlo.

«Corra um espelho privado e avaliado» falha o argumento da mesma forma: os pacotes que importam para a experimentação são os que ninguém ainda avaliou. Um espelho de dependências aprovadas é um espelho das ideias de ontem.

Por isso a questão não é como impedir os programadores de tocar em código não avaliado. Têm de o fazer; é essa a função. É como deixá-los tocar em tudo, livremente, sem que o seu chaveiro faça parte do negócio.

A sandbox construída para produção não serve para a bancada.

O primeiro reflexo é uma sandbox de rede — os contentores endurecidos, os da NVIDIA, as receitas de Docker-Compose que circulam por aí. A forma é sempre a mesma: enumerar os hosts que o agente pode alcançar, negar o resto. Funciona lindamente quando o agente tem uma função conhecida e estreita. Um agente de produção a falar com três serviços internos e um endpoint de modelo vive atrás de uma lista de permissões para sempre, porque a lista é curta e deixa de mudar.

A ideação não tem lista curta, e nunca deixa de mudar. Ninguém quer manter uma whitelist de cada registry, CDN, host de Git, e API pontual que uma experiência possa alcançar — nunca está acabada, cresce todas as tardes, e o dia em que bloqueia algo legítimo é o dia em que o programador a desativa para se desbloquear. A lista de permissões não está errada; protege um agente cujo escopo já é conhecido. O valor todo da bancada é que o escopo ainda não é conhecido.

Pegue numa tarde concreta. Um programador tem ficheiros de configuração Node que cresceram para dezenas de megabytes, e o parser de YAML em que está engasga-se com eles. Há vários candidatos — js-yaml, yaml, yaml-js — e a única forma de saber qual sobrevive a um ficheiro de 40 MB sem rebentar a heap é instalar os três e atirar o ficheiro a cada um. Abrir um ticket para pôr três bibliotecas no espelho privado para que possam ser avaliadas em benchmark é exatamente ao contrário: o programador quer testar primeiro e promover o vencedor para o espelho, não o contrário. A pré-avaliação é o portão pelo qual a experiência existe para passar.

Há um problema mais silencioso por baixo. Estas ferramentas endurecem o agente em produção — implantado, com escopo, supervisionado. Mas um comprometimento da cadeia de fornecimento aterra no portátil do programador, a meio de uma experiência, com credenciais reais em ~/.aws e ~/.npmrc porque é onde os programadores as guardam. O modelo é mais forte onde os ataques não estão, e ausente onde eles estão.

A sandbox de gato-e-rato perde a segunda ronda.

O outro instinto é deixar o agente no host e prender o processo — bloquear o processo claude de ler ~/.ssh e ~/.aws. Parece estanque, até se lembrar de que a função do agente é escrever código, e o código corre na mesma máquina.

O agente faz o scaffolding de um projeto. Depois você — ou o agente, ou uma segunda ferramenta — corre npm install no repositório que ele acabou de escrever. Esse npm install não é o processo preso. O seu hook postinstall~/.aws/credentials como qualquer outro programa no seu portátil, porque é exatamente o que é: outro programa, a partilhar o único sistema de ficheiros e o único chaveiro com tudo o resto que você corre.

O SEU PORTÁTIL — um sistema de ficheiros, um chaveiroPRISÃO DE PROCESSOclaude✗ read ~/.ssh✗ read ~/.awsbloqueado — parece estanque./repo — acabado de escrever pelo agentepackage.json "postinstall": "node x.js"SEGUNDA SHELL — não presa$ npm install corre postinstallum processo diferente que a prisão não nomeouCHAVEIRO~/.aws/credentials~/.ssh/id_rsa~/.npmrctokens reais✗ a prisão recusa este caminholê creds reais — ninguém prendeu isto
O buraco do gato-e-rato. Uma prisão de processo bloqueia o processo claude do chaveiro (o caminho tracejado, recusado). Mas a saída real do agente — um repositório com um hook postinstall — corre num processo irmão de que a prisão nunca ouviu falar. Abra uma segunda shell, corra npm install, e o seu postinstall lê ~/.aws/credentials livremente e exfiltra, porque num só host todos os processos partilham um sistema de ficheiros e um chaveiro. A prisão traçou a sua fronteira em volta da coisa errada: o perigo nunca foi o processo nomeado, foi a máquina partilhada.

A prisão traçou a sua fronteira em volta de um processo. O perigo nunca foi o processo; foi que todos os processos na máquina partilham um sistema de ficheiros e um chaveiro. Por isso remenda — prende a shell também, depois o node, depois o gestor de pacotes — e o atacante continua a encontrar uma porta que não trancou, porque num só host há sempre outro processo, outro caminho para os mesmos segredos. É esse o jogo, e a casa tem sempre outra porta.

Trace a linha uma vez, com o hypervisor.

O Bromure deixa de jogar movendo a fronteira um nível abaixo. O agente, as shells que gera, os pacotes que instala, e qualquer código que esses pacotes corram vivem todos dentro de uma VM Linux por perfil. As suas credenciais reais nunca entram nela.

A diferença é o tipo de linha. Uma prisão de processo é uma política acerca de um processo, e um processo irmão contorna-a. A fronteira da VM é o muro entre convidado e host, imposto pelo hypervisor — o mesmo muro que impede uma VM de ler a memória de outra. Não há syscall para o atravessar. O código de dentro não consegue raciocinar o seu caminho até ao seu chaveiro, porque o chaveiro não está sequer no mundo dele.

E dentro dessa linha, você é livre. Instale o pacote não avaliado. Corra o seu postinstall. Deixe o agente reescrever a sua configuração de shell, encher o disco, partir a toolchain. A VM é descartável e nunca guardou nada que importe. Essa liberdade é o ponto todo — exatamente o que uma sandbox tira e o que uma fronteira limpa devolve. Não consegue segurança tornando a bancada menos útil; consegue-a tornando a bancada um lugar onde nada de valioso estava na sala para começar.

Essa mesma linha é onde três garantias deixam de ser conselhos que o agente pode anular e se tornam factos impostos por baixo dele — porque tudo o que a VM faz ao exterior tem de a atravessar.

Três coisas que a linha torna verdadeiras.

VM POR PERFIL — instale tudo, corra tudo, parta tudoagente · shells geradas · npm / pip · código postinstall não confiávelo sistema de ficheiros só tem stubs — aws_secret = stub-… _authToken = stub-… id_rsa = stub-…nada aqui é real, por isso nada aqui vale a pena roubarbuscar um pacoteusar uma credencialpush / drop / deleteFRONTEIRA DO HYPERVISOR — a linha que o código de dentro não pode cruzar① Bloquear pacotes maliciososanálise: OSV + socket.devcooldown: < 2 dias retidoo tarball malicioso nunca aterra② Sem creds para roubarstub-token ⇄ real tokentrocado no fioa varredura no host só acha placeholders③ Perguntar antes de mutarleitura passa · escrita pausapedido no hostvê a chamada literalHOST — tokens reais, atrás do broker~/.aws · ~/.ssh · ~/.npmrc — nunca entram na VM, trocados só no fio, só para uma chamada que permitiu
Uma fronteira, três controlos, impostos por baixo do agente. Dentro da VM o agente faz o que quiser. Mas cada travessia é mediada pelo hypervisor: uma busca de pacote é analisada (OSV + socket.dev) e retida se for mais nova que o cooldown; um uso de credencial encontra um stub que o proxy do host troca pelo token real no fio e volta a trocar; uma escrita que muda estado faz uma pausa para um pedido no host. O chaveiro real está por baixo da linha e nunca entra na VM. O agente não consegue contornar nada disto, porque não há caminho através da fronteira a não ser por ela.

Nenhuma credencial para roubar — o segredo nunca esteve na sala.

Os tokens reais ficam no host. A VM recebe stubs: ficheiros de credenciais sintaticamente válidos cujo conteúdo não significa nada na internet pública. Quando o agente faz uma chamada legítima que precisa de um token real, um proxy do host troca o stub pelo segredo real no fio e volta a trocá-lo na resposta. Uma dependência comprometida a varrer o sistema de ficheiros à procura de ~/.aws/credentials, ~/.npmrc, ou id_rsa encontra placeholders. Isto é a troca de token: a credencial existe, o agente usa-a para aquilo a que se destina, e a cópia que poderia ser roubada não existe em lado nenhum que o mundo do agente alcance.

Estreite o token amplo — perguntar antes de usar, perguntar antes de mutar.

Os tokens reais são normalmente mais amplos do que a tarefa. O broker mantém as concessões efémeras e com escopo, e — a parte que justifica o seu valor — trata uma leitura e uma escrita de forma diferente. Uma leitura passa. Uma chamada que muda estado — um git push, um DROP TABLE, um Terminate* da AWS — faz uma pausa na fronteira e pergunta-lhe, no host, mostrando a operação literal, não um resumo que o agente escreveu.

Isso muda o que um token amplo significa. Um que poderia apagar produção só o consegue fazer quando um humano viu a chamada exata e disse sim; o escopo impresso na credencial deixa de ser o raio de explosão. O agente não consegue pré-aprovar-se, rebaixar o modo, ou ler a concessão — a decisão vive no lado de lá da linha. Quando um agente apagou uma base de dados de produção em nove segundos, o princípio era o mesmo: a coisa que quer correr o comando não devia ser a coisa que decide que ele é seguro.

Não seja o primeiro a descobrir — cadeia de fornecimento travada à porta.

O melhor momento para travar um pacote envenenado é antes de ele aterrar. Cada busca atravessa a fronteira, por isso o proxy analisa-a — OSV para CVEs conhecidos, socket.dev para o que as bases de dados ainda não apanharam: scripts de instalação maliciosos, typosquats, o comprometimento publicado há uma hora. E impõe um cooldown: qualquer release dos últimos dois dias (ajustável) é simplesmente não instalável enquanto o ecossistema se atualiza. A janela toda de um worm é o intervalo entre publicar e retirar; recusar pacotes com um dia é recusar ser o canário. Os hooks postinstall são removidos do tarball à entrada, com o hash corrigido para que a instalação continue a verificar — por isso o pacote que aterra aterra inerte. Nada disto pede ao programador que avalie seja o que for. Puxam o que quiserem; a fronteira é o que espera.

Onde todo o resto fica para trás

A maioria das ferramentas cobre uma camada. O Bromure cobre todas elas.

Isolamento, manter os segredos fora do agente, limitar como eles são usados, escanear a cadeia de suprimentos, barrar a injeção de prompt — a área costuma escolher só uma. Aqui está o mesmo modelo de ameaça do agente aplicado às ferramentas a que as pessoas recorrem, e onde cada uma termina.

Proteção
Dev ContainerVS Code
nonokernel sandbox
agent-vaultoctokraft
Agent VaultInfisical
Docker SandboxesmicroVM
BromureAgentic Coding
Fronteira de isolamento
Onde o raio de dano para
Mesmo contêiner, kernel compartilhado
Allowlists de kernel, sem kernel próprio
O agente roda no lugar
Só proxy; agente sem isolar
microVM, seu próprio kernel
VM por hardware, seu próprio kernel
Manter os segredos fora do agente
Ele consegue ler a credencial real?
Encaminha o agente SSH + creds do git
Bloqueia arquivos de chave; intermedia alguns
Injetados por pipe; sem caminho de leitura
O proxy as anexa no fio
O proxy do host injeta cabeçalhos
Stub trocado no fio
Escopo e aprovação de credenciais
Limites por uso, somente leitura, expiração, consentimento
Sem escopo por uso
Fluxo de aprovação + filtro de egresso
TTL por segredo; bloqueia shells
Filtro de egresso por endpoint
Allowlist de domínios; o código na VM ainda pode usá-la
Consentimento por destino + TTL
Varredura da cadeia de suprimentos
Capturar pacotes maliciosos / vulneráveis
Sem varredura do registro
Só assinatura, sem varredura de pacotes
Fora do escopo
Fora do escopo
Sem varredura de pacotes
Age-gate, OSV, socket.dev
Detecção de injeção de prompt
Varre conteúdo não confiável e arquivos de regras
PromptGuard + ModernBERT
Trilha de auditoria
Registrar o que o agente fez
Só logs do contêiner
Auditoria local imutável
Registro de requisições
Registro de requisições
Trace de sessão completo, criptografado
Inventário da cadeia de suprimentos(Enterprise)
Um registro de cada pacote baixado
Cada dependência + veredito, pesquisável
Uso de tokens(Enterprise)
Quais arquivos consomem mais tokens
Por arquivo, repo e modelo
Total — embutido, imposto Parcial — limitado ou opcional Nenhum — não tratado

Ocultar um token não é o mesmo que governar seu uso. O Docker Sandboxes mantém o valor real fora da VM, mas seu proxy ainda anexa essa credencial a qualquer requisição de saída que a sandbox faça, então um pacote comprometido instalado por fora pode gastá-la contra um serviço da allowlist sem nunca vê-la. Só o Bromure escaneia o pacote antes de ele rodar e condiciona cada uso — consentimento, somente leitura, um TTL — impondo os cinco controles em uma única fronteira que o agente não consegue contornar.

Compilado da documentação pública de cada projeto, junho de 2026. Aqui, agent-vault se refere a octokraft/agent-vault (injeção de segredos por pipe), distinto do Agent Vault da Infisical (proxy de credenciais HTTP). O Docker Sandboxes é uma prévia experimental cujas credenciais intermediadas continuam utilizáveis por qualquer coisa dentro da VM. O inventário de pacotes de toda a frota e os detalhamentos de uso de tokens são oferecidos no Bromure Enterprise Manager. Essas ferramentas mudam rápido — viu algo desatualizado? Avise a gente.

A quarta coisa: uma instrução nos dados não é uma ordem.

As três garantias acima partilham uma assunção que vale a pena trazer à superfície: todas defendem contra código que tira algo — uma credencial, um token, a oportunidade de um tarball fresco correr. Há um ataque que não tira nada. Limita-se a dizer ao agente o que fazer. Uma linha enterrada num README que o agente lê, uma string numa página buscada, uma frase na saída de uma ferramenta, uma diretiva escondida no CLAUDE.md que o agente trata como ordens permanentes — o modelo ingere-a como contexto e obedece-lhe como instrução. Vaze o ficheiro. Enfraqueça a verificação. Salte o teste. Uma sandbox não tem opinião sobre nada disto, porque nada cruzou um muro que ela vigie: a instrução chegou como dados, em conteúdo que o agente era suposto ler.

Mas cruzou a linha — tudo o que o modelo vê cruza-a. Por isso, desde a 2.4.0, a fronteira lê-o primeiro, no dispositivo, do lado do host. Um classificador PromptGuard local pontua o conteúdo não confiável que flui para o modelo — leituras de ficheiros, buscas web, saída de ferramentas — à procura de instruções que não têm nada que lá estar. E os ficheiros de regras a que um agente obedece sem questionar — CLAUDE.md, AGENTS.md, GROK.md — recebem uma dupla passagem mais severa: uma análise determinística de Unicode invisível, truques de texto bidirecional e meta-diretivas no estilo «ignore as instruções anteriores», mais um classificador ModernBERT ajustado para o abuso redigido em tom calmo que um filtro de palavras-chave deixa passar. Por perfil, escolhe os dentes: registrar no Security Log, perguntar e ver o texto sinalizado, ou bloquear o pedido antes de o modelo sequer ver o trecho envenenado. Nada sai do Mac.

A colocação é o mesmo argumento das outras três. Um agente que já engoliu uma injeção não é de confiança para a reportar — a primeira instrução da injeção é normalmente alguma versão de não mencione isto. O detetor não pergunta ao agente. Lê o tráfego no lado de lá da linha, onde a persuasão do agente não chega.

Onde a linha não o salva.

Uma fronteira é uma forma específica, não uma palavra mágica. Quatro margens honestas:

O perfil é de longa duração, por isso a persistência persiste.

Um perfil do Bromure não é um disco descartável. Um payload que se escreve a si mesmo num caminho de arranque pode acordar na sessão seguinte — para um convidado sem chaves do host e um broker que só fala tokens efémeros, pedidos e com escopo. Presença numa sala sem nada dentro, mas presença na mesma.

Uma escrita que aprova é uma escrita que acontece.

O pedido apanha a chamada de que o agente não lhe falou. Não lê o seu diff. Aprove um git push e o Bromure encaminha-o — incluindo, em princípio, um workflow envenenado que não reparou. Move a decisão para si e mostra a operação real; lê-la continua a ser a sua função.

O cooldown é uma janela, não um muro.

Dois dias estão ajustados ao intervalo observado entre publicar e retirar. Um atacante paciente pode sentar-se sobre uma versão comprometida para lá do cooldown e ficar instalável ao terceiro dia. Esfomeia os worms do mesmo dia; não responde por um pacote que apenas envelheceu. O socket.dev e o OSV ainda têm de fazer a sua parte.

Dê escopo ao broker de propósito.

O isolamento contém a explosão; o escopo decide quão grande ela poderia ter sido. Um perfil que só lê um repositório não devia ter um token que o escreve; um que nunca publica não devia ter token de publicação. A linha mantém os segredos fora da VM — quais segredos existem afinal continua a ser decisão sua.

A linha que vamos manter.

Eis o compromisso. Um programador não devia ter de se tornar um administrador de sistemas — manter uma lista de permissões, pré-validar cada dependência, abdicar da velocidade que tornou um agente digno de ser usado — para manter o seu chaveiro. Uma sandbox faz da segurança uma troca contra a utilidade, e os programadores, sensatamente, continuam a escolher a utilidade. Uma fronteira recusa a troca: faça tudo do lado de dentro, porque o lado de dentro é dispensável, e as quatro coisas que importam — as suas credenciais, o escopo dos seus tokens, os pacotes que o alcançam, as instruções que alcançam o seu modelo — são decididas numa linha com a qual o código de dentro não consegue discutir.

É por isso que «é uma sandbox» é a descrição que continuaremos a corrigir. Uma sandbox restringe o agente. O Bromure restringe a fronteira, e liberta o agente. O Bromure Agentic Coding é gratuito, de código aberto, e já disponível hoje.