A regra de permissão guardou a senha
Em 6 de novembro, a Apiiro relatou que o botão “Yes, and don't ask again” do Claude Code salva o comando aprovado, segredos incluídos, em .claude/settings.local.json, e que 1.122 repositórios públicos do GitHub tinham feito commit desse arquivo com senhas, tokens e chaves com cara de válidos. Dois scanners de segredos populares deixaram passar 215 deles. No Bromure Agentic Coding, todo segredo que o agente consegue digitar é um substituto, então uma regra salva guarda um valor que não funciona em lugar nenhum, e todo push espera por você no Mac.
Você clica em “Yes, and don't ask again” para uma pergunta não voltar mais. O Claude Code guarda o comando inteiro para reconhecê-lo da próxima vez, senha incluída, num arquivo dentro do seu projeto.
Em 6 de novembro, a Apiiro publicou uma pesquisa sobre agentes de código que vazam segredos pelo “don't ask again”. O The Hacker News noticiou na manhã seguinte.
O mecanismo é banal. Quando o Claude Code pede para rodar um comando de shell
e você escolhe Yes, and don't ask again, ele grava uma regra de permissão
em .claude/settings.local.json, no projeto. Às vezes a regra é um padrão
como npm test *. Às vezes é o comando exato, e quando esse comando tinha uma
senha depois de PGPASSWORD=, sshpass -p ou mysql -p, a senha agora está
num arquivo JSON ao lado do seu código.
A Apiiro procurou esse arquivo no GitHub público e encontrou:
- 104.185 cópias em 103.617 repositórios;
- 1.122 cópias com pelo menos um segredo, 1.379 segredos distintos no total;
- 379 senhas de bancos de dados, 43 logins SSH de servidores públicos, 42 tokens do GitHub, GitLab e npm, e 23 chaves da AWS;
- segredos de 63 organizações, incluindo uma chave de nuvem com nível de administrador de um fornecedor de bancos de dados e a senha de proprietário de um banco de prontuários médicos.
Todos esses arquivos ainda estavam no branch padrão quando a Apiiro
verificou. Em metade dos repositórios, estavam lá havia pelo menos 217 dias.
Commits mais antigos guardavam mais 734 segredos em 509 repositórios, e 211
forks de 74 repositórios carregavam cópias. Somando o .claude/settings.json
compartilhado, o histórico e os logs de chat de agentes salvos, a Apiiro
contou 2.539 segredos em 1.994 repositórios.
Por que passou por tudo
O Claude Code tenta, sim, manter o arquivo fora do git. Na primeira vez que
grava settings.local.json, ele adiciona o arquivo às suas exclusões
globais do git. Essa regra vive em um único computador. O notebook de um
colega, um runner de CI ou um clone novo não a têm, e ela não faz nada por um
arquivo que já foi commitado. O Claude Code nunca adiciona o arquivo ao
.gitignore do próprio projeto. Dos 16 agentes de código que a Apiiro
comparou, o Claude Code é o único confirmado que salva por padrão o comando
aprovado completo num arquivo do projeto.
Os scanners de segredos não se saíram melhor. A Apiiro rodou o gitleaks e o
TruffleHog em cada cópia. O gitleaks apontou 564 dos 1.122 arquivos, o
TruffleHog 643, e 215 escaparam dos dois. A maioria desses 215 eram senhas
digitadas em comandos. Os scanners procuram formatos de chave conhecidos como
AKIA… ou ghp_…, e sshpass -p hunter2 não bate com nenhum deles.
Usuários relataram o problema há mais de um ano. Uma issue de agosto de 2025, anthropics/claude-code#5544, dizia que o Claude Code guardava nesse arquivo, palavra por palavra, comandos aprovados com chaves de API. Um bot a fechou como “not planned” depois de 60 dias sem atividade. Outros quatro relatos relacionados tiveram o mesmo destino com o mesmo bot, o mais recente na véspera do artigo do The Hacker News.
O segredo estava no comando porque estava nas mãos do agente
Cada um desses 1.379 segredos era um valor que o agente conseguia digitar. Um
desenvolvedor o colou no chat, ou deixou num arquivo .env, ou o agente o
leu de ~/.aws/credentials ou ~/.pgpass e o embutiu no comando que queria
rodar. A regra de permissão anotou o que o agente já tinha.
O conselho da Apiiro para o futuro vai na mesma direção: manter segredos fora
dos comandos e referenciar uma variável de um gerenciador de segredos, para
que a regra salva contenha só $DB_URL. Isso ajuda se todo desenvolvedor e
todo agente seguir a regra todas as vezes. Um agente tentando fazer um
comando com erro funcionar vai expandir a variável. O Bromure vai pelo outro
caminho e mantém o valor real totalmente fora do ambiente do agente.
O mesmo clique, no Bromure Agentic Coding
O Bromure Agentic Coding roda Claude Code, Codex, Grok, Kimi e omp em VMs Ubuntu no seu Mac. O agente recebe credenciais pelo que chamamos de fronteira do fio: dentro da VM, todo segredo é um substituto, e o valor real fica criptografado no Mac, com a chave mestra no Keychain do macOS. Um proxy no Mac troca o substituto pelo valor real no fio, e só numa requisição para o host ao qual aquela credencial pertence.
Então, quando o agente pede para rodar um comando com um token e você escolhe Yes, and don't ask again, o Claude Code salva o comando exatamente como antes. O token dentro dele é o substituto.
Todo segredo que o agente consegue digitar é um substituto
Os substitutos mantêm o formato que as ferramentas esperam, então nada muda no projeto:
| O que a Apiiro encontrou vazado | O que o agente tem numa máquina Bromure |
|---|---|
| Tokens do GitHub e do GitLab | ghp_ + 36 caracteres, glpat- + 20, em GH_TOKEN, GITLAB_TOKEN e ~/.git-credentials |
| Tokens do npm | um valor brm_… em NPM_TOKEN, de uma entrada Other API key restrita a registry.npmjs.org |
| Chaves da AWS | o ID real da chave de acesso com uma chave secreta falsa; o Mac reassina cada requisição com a real |
| Senhas de bancos de dados | um valor brm-db-… na variável que você escolher, para ClickHouse, a Mongo Data API e o Elasticsearch |
| Logins SSH | nenhuma senha: assinaturas feitas por chaves que ficam no Mac |
Pegue um comando que um agente poderia rodar contra um endpoint do ClickHouse:
curl -u default:brm-db-7Qk2…Xw9 \
'https://analytics.example.com:8443/?query=SELECT+count()+FROM+events'
Aprove para sempre e a regra de permissão guarda brm-db-7Qk2…Xw9. O proxy
troca o substituto nas requisições para analytics.example.com, no cabeçalho
Basic-auth e no corpo da requisição, já que segredos de banco de dados
costumam viajar dentro de SQL e JSON. Em qualquer outro lugar, a string não
serve para nada.
Na AWS, o segredo nunca chega à VM. O ~/.aws/config do agente aponta para
um auxiliar que entrega o ID real da chave de acesso com um segredo falso de
40 caracteres. A AWS CLI, o boto3 e o terraform assinam com o falso, e o Mac
remove essa assinatura e reassina com o segredo real antes de a requisição
sair. A chave secreta real nunca existe na VM, então nenhum comando que o
agente escreva pode contê-la.
O SSH cobre os 43 logins de servidores da contagem da Apiiro. O
SSH_AUTH_SOCK de uma máquina Bromure é uma ponte para o Mac: a VM pode
pedir assinaturas, e os bytes da chave privada nunca atravessam. Chaves
protegidas por YubiKey, Secretive ou 1Password podem ser oferecidas uma a
uma, com o pedido de toque no seu Mac. O agente nunca precisa de
sshpass -p, então não há senha para uma regra de permissão salvar.
Um substituto no GitHub não abre nada
Digamos que o arquivo chegue mesmo a um repositório público, a um fork e a
uma dúzia de commits antigos. Quem o raspar recebe ghp_ e 36 caracteres que
o GitHub nunca emitiu. Enviado do notebook dessa pessoa, falha na
autenticação. Só o proxy do seu Mac sabe a qual token real ele corresponde,
e esse proxy só atende a VM da sua máquina.
Se um substituto algum dia sair de dentro da máquina para o host errado, o proxy trata isso como uma tentativa de exfiltração. Ele bloqueia a requisição com HTTP 451, pausa a VM e abre um alerta intitulado This environment may have been compromised que mostra a credencial, o host ao qual ela pertence e o host para onde foi enviada. Assim, cada substituto também é uma armadilha, além de um marcador.
A rotação acontece num só lugar
A primeira instrução da Apiiro é rotacionar toda senha, token e chave que o
arquivo já guardou, antes de limpar qualquer coisa. Com segredos reais
espalhados por arquivos .env, histórico do shell e configuração do agente,
isso é uma caçada. No Bromure, os valores reais ficam num só lugar: o painel
Credentials da máquina, no Mac. Cole o novo token lá e o substituto na VM
continua o mesmo, então as regras de permissão, scripts e configurações
dentro da máquina continuam funcionando.
Uma Other API key também pode ser uma referência do 1Password como
op://Engineering/npm/token. O Bromure a resolve no Mac e a resolve de novo
a cada 2 minutos, então uma chave rotacionada no 1Password passa a valer em
poucos minutos, sem reiniciar e sem nada para editar na VM.
Levar os segredos para esse painel é um passo só. Import env file… lê um
.env ou ~/.bashrc existente, mostra as variáveis com os valores
mascarados e as transforma em credenciais. A pasta do projeto deixa de
precisar do arquivo .env de onde o agente lia as senhas.
O push espera por você
Em 539 dos repositórios que a Apiiro rastreou, um commit que creditava o Claude como coautor alterou o arquivo. Agentes fazem commit e push como parte de terminar uma tarefa.
Nas máquinas Bromure novas, todo serviço de forge começa em Prompt before
write no painel Guardrails. Leituras passam. Um git push por HTTPS
para num diálogo no Mac que mostra a operação, e nada sai até você
responder. A política roda no proxy, então nada dentro da VM consegue
desligá-la.
Um revisor que lê a linha
Os 215 segredos que nenhum scanner pegou eram senhas dentro de comandos. Um
modelo que lê PGPASSWORD=… psql -h db.example.com num arquivo JSON
commitado sabe o que está vendo.
Uma code review do Bromure acompanha um repositório do GitHub com um agente em uma das suas máquinas, em Every new commit, Every new pull request ou numa agenda semanal, e o Bromure elimina achados duplicados entre varreduras. Para o passo da Apiiro “procure na sua organização, histórico incluído”, Run Baseline Now inicia uma revisão avulsa do repositório inteiro. O GitHub é consultado a partir do Mac, e o agente de revisão trabalha com os mesmos substitutos que qualquer outro.
A transcrição também guarda o substituto
A contagem da Apiiro incluía logs de chat de agentes salvos. Os arquivos de
sessão do próprio Claude Code na VM registram o que o agente viu, e numa
máquina Bromure isso é o substituto. Os traces do Bromure no Mac guardam as
trocas de token como prévias curtas do tipo sk-a…f9q3, e os bytes do segredo
real nunca entram num registro de trace. Quando um segredo com cara de real
aparece mesmo assim no tráfego, porque alguém o colou à mão na VM, o trace o
marca como possível vazamento, e bromure-cli trace leaks lista todos.
Ative Only allow credentials Bromure injects em Guardrails, e uma
requisição com uma credencial que o Bromure não colocou ali é bloqueada e
dispara o alerta de comprometimento.
Substitutos em todo comando
Tokens, segredos de banco de dados e chaves da AWS são substitutos na VM. Uma regra de permissão salva um valor que só funciona através do seu Mac.
Sem senha para SSH
A VM pede assinaturas ao Mac. A chave privada nunca atravessa, e
sshpass -p nunca é necessário.
Pushes esperam no Mac
Prompt before write é o padrão em máquinas novas. Um push espera sua resposta, e quem impõe isso é o proxy.
Rotacione uma vez
Os valores reais ficam num só painel, ou no 1Password. Troque-os lá e todo substituto continua funcionando.
O que fazer esta semana
Da lista da Apiiro, para toda equipe que usa agentes de código:
- Procure
.claude/settings.local.jsone.claude/settings.jsonna sua organização do GitHub, histórico incluído. - Rotacione todo segredo que esses arquivos já guardaram e depois faça a limpeza.
- Rode
git rm --cached .claude/settings.local.jsone adicione o arquivo ao.gitignoredo projeto e aos templates da sua organização. - Trate
.claude/,.cursor/,.gemini/e.specstory/como arquivos.envna varredura de pre-commit e de CI, e garanta que o scanner pegue senhas dentro de comandos.
Depois, tire os segredos reais do alcance do agente. Numa máquina Bromure, o próximo “don't ask again” salva um substituto, quer o desenvolvedor tenha se lembrado das regras da Apiiro naquele dia, quer não.
Para o padrão mais amplo de agentes que copiam segredos para o histórico e os logs, veja A transcrição guardou o token. Para entender a troca em detalhe, leia o capítulo Credentials do manual.