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

As chaves estavam no console deles

Na noite de 16 de outubro, alguém entrou em um sistema legado da OpenCode e alcançou as chaves de API da OpenAI, Anthropic e Google que cerca de 1,4% dos usuários do OpenCode Console tinham salvado em seus workspaces. A OpenCode chamou o caso de ataque de destilação em larga escala, e usuários relataram faturas de provedores que não geraram. No Bromure Agentic Coding, as chaves dos provedores ficam criptografadas no seu Mac, o roteamento entre vários provedores roda no seu Mac, e qualquer cópia de uma chave que sai da VM é um substituto que nenhum provedor aceita.

Seu laptop estava em ordem. Sua chave da Anthropic foi roubada de um servidor onde você a colou meses atrás.

No sábado, 17 de outubro, a OpenCode avisou parte dos seus usuários de que havia “identified unauthorized access to a legacy system”, um sistema que estava em processo de desativação. A invasão aconteceu durante a noite, de 16 para 17 de outubro. O aviso dizia que “third party provider keys (eg OpenAI, Anthropic) saved in your workspace may have been exposed”. A OpenCode estimou a parcela de usuários do OpenCode Console afetados em cerca de 1,4%, restrita a contas com provedores externos vinculados, e mandou e-mail para cada uma delas. Descreveu o incidente como “related to a large scale distillation attack” e disse estar trabalhando com a Anthropic, a OpenAI e o Google. OfficeChai, Startup Fortune e outros noticiaram no mesmo dia.

A OpenCode disse que não podia confirmar se as chaves tinham sido usadas e que o incidente ainda estava em andamento. Usuários no X relataram cobranças em chaves que só tinham usado com a OpenCode, algumas na casa das centenas de dólares. O conselho publicado por todos foi o mesmo: revogar cada chave salva no Console pelo painel de cada provedor, emitir novas e atualizar todos os lugares onde a chave antiga estava.

As vítimas não tinham rodado um pacote malicioso nem aberto um repositório envenenado. Um invasor pegou as chaves delas de um servidor onde elas as tinham colado.

Por que as chaves estavam lá

A OpenCode é um agente de programação de código aberto que conversa com mais de 75 provedores de modelos. O Console é a parte hospedada, onde você pode salvar suas próprias chaves de provedores em um workspace e deixar o serviço usá-las por você. O resumo do ai-tldr as descreve como chaves salvas “for bring-your-own-key use”. É uma conveniência: uma conta, todos os provedores, nada de ficar levando chaves de um laptop para outro.

Também transforma o banco de dados de um fornecedor em um chaveiro. Cada usuário que vinculava um provedor acrescentava mais uma credencial ativa e cobrável ao mesmo armazenamento. Meses depois, um sistema que o fornecedor estava aposentando ainda tinha acesso a esse armazenamento.

Uma chave de API de modelo é poder de gasto. Quem a tem pode comprar inferência na sua conta até você revogá-la, no ritmo que o provedor permitir. O motivo relatado, “destilação”, significa colher em volume as respostas de um modelo forte para treinar um mais barato. Isso exige muitas requisições, e uma chave roubada faz outra pessoa pagar por elas.

Uma cópia, no seu Mac

O Bromure Agentic Coding roda Claude Code, Codex, Grok, Kimi e omp em VMs Linux no seu Mac. Você registra cada provedor de modelos uma única vez, em Preferences › Models: cole uma chave de API ou clique em Sign in with provedor para usar uma assinatura do Claude, ChatGPT, Grok ou Kimi sem chave de API nenhuma.

As chaves vão para models.enc, na pasta de suporte do app, criptografadas com AES-GCM sob uma chave mestra própria de cada instalação. Essa chave mestra fica no Data Protection Keychain do macOS, vinculada à identidade de assinatura do app, com a sincronização do iCloud desligada. Ela nunca sai do Mac. O Bromure não tem uma conta onde suas chaves morem, nem um workspace hospedado para onde elas sincronizem.

O Bromure oferece a conveniência do console no próprio Mac. Toda máquina lê o mesmo quadro, e uma máquina pode sobrepô-lo com suas próprias chaves. Codex, Grok, Kimi e omp podem chegar ao Bedrock, OpenRouter, xAI e Moonshot por um proxy de tradução que roda no Mac e guarda a chave real ali. O Claude Code chega ao OpenRouter e ao z.ai diretamente, com um substituto.

Onde fica a chave realChaves salvas em um console hospedadoSeu laptopColegaOutros usuárioschaves reaisArmazenamento do fornecedorsk-ant-… sk-proj-… AIza…as chaves de cada usuário vinculadoSistema legado, em desativaçãoInvasor roda inferência em massaA conta vai para o dono da chave até ela ser revogada.Chaves no Bromure Agentic CodingSeu Mac · models.encAES-GCM, chave mestra no Data Protection KeychainVM Linux · ambiente e config do agenteANTHROPIC_API_KEY=sk-ant-api03-brm-… (substituto)Proxy no Mac verifica o destino de cada requisiçãoapi.anthropic.comsubstituto → chave realqualquer outro host451, VM pausadaNenhuma cópia hospedada. A VM só tem substitutos.
À esquerda: chaves salvas em um console hospedado dividem um servidor com as chaves de todos os outros usuários, e uma única invasão alcança todas. À direita: no Bromure, a chave real existe em um arquivo criptografado no seu Mac e na requisição que o Mac envia ao provedor. Tudo o que a VM guarda é um substituto, e um substituto enviado para qualquer outro lugar para a máquina.

Tudo na VM é um substituto

O agente ainda precisa de ANTHROPIC_API_KEY ou OPENAI_API_KEY para iniciar, e recebe uma. Dentro da VM, essas variáveis guardam substitutos com o formato das chaves reais: sk-ant-api03-brm-… para a Anthropic, sk-brm-… para a OpenAI, xai-brm-… para a xAI, sk-kimi-brm-… para o Kimi. O HTTPS do agente passa por um proxy no Mac, que troca o substituto pela chave real apenas em requisições para os hosts do próprio provedor: anthropic.com, openai.com, x.ai, moonshot.ai. A correspondência é exata ou por subdomínio, nunca por substring, então api.openai.com.evil.example não recebe nada.

Com uma assinatura é igual, só que sem a chave. O login acontece em uma VM descartável ou pelo próprio login do agente, o proxy captura os tokens OAuth no Mac, e o agente fica com um substituto. O host renova o token de acesso cerca de cinco minutos antes de ele expirar. A VM nunca guarda um refresh token.

Muitas ferramentas agora oferecem sincronizar suas configurações com a nuvem do fornecedor: uma CLI que faz “backup” da config, um editor que mantém seu workspace na sua conta, um plugin com painel. Dentro de uma máquina Bromure, a config que essas ferramentas enviam contém sk-ant-api03-brm-…. Um substituto guardado no servidor de outra pessoa não vale nada lá. Nenhum provedor o aceita, e ele só vira uma chave real quando a requisição passa pelo seu Mac a caminho do provedor para o qual foi criado.

O proxy também pega o próprio envio. Ele examina cada requisição de saída, cabeçalhos e corpo, em busca de substitutos indo para outro destino que não o seu próprio provedor. Uma sincronização de config que leva um substituto da Anthropic a um servidor de terceiros recebe HTTP 451. Nada é encaminhado, a VM é pausada e o Mac mostra This environment may have been compromised, informando a prévia do token, a credencial, o host a que ela pertence e o host para onde foi enviada. Você fica sabendo no dia em que uma ferramenta tenta copiar sua chave para fora da máquina, meses antes do aviso de violação de qualquer fornecedor.

A manhã seguinte, no Bromure

Digamos que você tenha recebido aquele e-mail mesmo assim, porque também usou uma chave em outro lugar. Todo guia diz as mesmas três coisas: revogar, substituir em todo lugar e verificar o uso. No Bromure, cada passo é curto.

Substituir em todo lugar. A chave real fica em um só lugar. Cole a nova no popover do provedor em Preferences › Models e o Bromure atualiza cada máquina em execução cerca de um segundo e meio depois que você para de digitar: o mapa de troca, o ambiente dos agentes e os arquivos de config deles. Os agentes cuja credencial mudou reiniciam na sua aba com as flags de retomada, então a conversa continua, e a VM nunca reinicia. Não há arquivos .env, segredos de CI nem laptops de colegas para caçar em busca das cópias dentro das VMs, porque essas cópias eram substitutos.

Verificar o uso. No nível AI request details, com o qual as máquinas novas começam, o Mac registra cada troca com um provedor de modelos como um registro llm.request: provedor, host, modelo, status e contagens de tokens de entrada, saída e cache. Quando o painel de um provedor mostra um pico às 3 da manhã, você pode compará-lo com o que suas máquinas enviaram. bromure-cli trace summary e bromure-cli trace hostnames dão a visão por máquina em um terminal. Cada troca de uma chave de provedor aparece na Security Timeline como uma linha Credential brokering, com uma prévia mascarada e o host, em uma tabela com uma coluna Workspace. Qualquer coisa na conta do provedor que suas máquinas não enviaram veio de outra pessoa.

Para uma equipe, o Bromure Enterprise Manager consolida as mesmas contagens de llm.request por usuário, por workspace e por modelo, sem enviar prompts, respostas ou segredos. Uma chave roubada aparece como um gasto que não corresponde a nenhuma instalação.

Ou dispense a chave. Para Claude Code, Codex, Grok e Kimi, um login com assinatura substitui a chave paga por uso, e os tokens gerados ficam no Mac e são renovados ali. Assim não sobra nenhuma chave de API de longa duração para um terceiro guardar.

Uma cópia criptografada, no seu Mac

Chaves de provedores e logins ficam em models.enc, sob uma chave mestra no Data Protection Keychain. O Bromure não tem workspace hospedado nem conta que os guarde.

Roteamento entre provedores, localmente

Toda máquina lê um único quadro Models. Os agentes chegam a outros provedores por um proxy no Mac que guarda a chave real.

Substitutos onde quer que uma cópia vá parar

A VM, seus arquivos de config e tudo o que uma ferramenta sincroniza com a nuvem guardam substitutos. Um substituto enviado ao host errado recebe um 451 e pausa a máquina.

Troque uma vez, audite por requisição

Uma chave nova chega a cada máquina em execução sem reinicialização. Cada troca com um modelo é registrada com o modelo e as contagens de tokens.

Onde uma chave deveria morar

Cada lugar onde você cola uma chave de provedor é mais um lugar de onde ela pode ser roubada. Laptops pegam stealers, repositórios são raspados e, como esta semana mostrou, fornecedores aposentam sistemas que ainda alcançam as chaves dos seus clientes.

Mantenha a chave real em um único arquivo criptografado no seu Mac e coloque substitutos em todos os outros lugares. Para a versão do mesmo problema do lado do laptop, leia O stealer levou os substitutos e O agente vazou a própria chave.