Guias de Segurança

Uma chave de API vazou de código escrito por IA e foi usada para cobranças fraudulentas: a causa foi uma vulnerabilidade CVSS 10.0 sem correção

Um app feito com ajuda da IA teve a chave de API roubada e acumulou cobranças. A causa real foi um RCE CVSS 10.0 sem correção. Como foi achada e como evitar.

Publicado 2026-06-07 Atualizado 2026-10-06 15 min de leitura
Nesta página

Um caso que desenvolvedores indie sem formação em segurança costumam enfrentar, com todo detalhe identificável removido e transformado em lição. Não há passos de reprodução de ataque aqui. O objetivo é a defesa, para que o mesmo erro não aconteça com você.

Ficha do caso — INCIDENT FILE
Classe
Vazamento de chave de API / cobrança fraudulenta
Severidade
Crítica (um CVSS 10.0 publicado foi abusado)
Causa raiz
Um RCE pré-autenticação no framework web ficou sem correção por meses
Escopo do vazamento
Todos os segredos do ambiente
Escopo da execução
Permaneceu dentro de um container sem privilégios (o root do host ficou intacto)
Correção permanente
①atualizar para a versão corrigida ②rotacionar todas as chaves ③monitorar CVEs por máquina
10.0
CVSS / pior classe
meses
tempo sem correção
todo o env
escopo de vazamento presumido
monitoramento
a prevenção mais eficaz

“Parou as cobranças” ≠ “resolvido”

Parar a fatura é uma medida temporária. Fechar o caminho do vazamento é uma tarefa separada. Você só termina quando faz as duas coisas.

O que aconteceu (linha do tempo)

  1. Dia 0 — publicado e em operação

    Um app criado com a ajuda da IA foi publicado e estava rodando em produção.
  2. Um dia — a fatura dispara

    A fatura da IA na nuvem salta de repente. Jobs em massa num modelo que jamais seria usado, fazendo um trabalho que não era seu.
  3. Investigação — abuso por terceiros

    "Nosso app saiu do controle" não explica. Um terceiro estava operando com uma chave roubada.
  4. Rastreamento — investigando o caminho do vazamento

    "Então, de onde a chave vazou?" Foi aqui que a investigação de fato começou.

Por que não foi pego de início

Na ordem em que os erros foram cometidos — porque os erros são a lição.

1

Decidiu a causa cedo demais

Primeira suposição: "nosso próprio código de fallback funcionou mal." Mas os dados (o que foi de fato processado) deixaram claro que não podia ser isso.
→ Antes de decidir "culpa minha" ou "culpa deles", olhe primeiro os dados.
2

Um grep limpo quase encerrou a busca

Todo o código, o histórico do git, os repositórios vinculados foram pesquisados → nenhuma chave em texto puro em lugar algum. Quase desistiu como "não rastreável". Olhando só para os arquivos, o vazamento em tempo de execução passou batido.
3

Esconder o sintoma pareceu corrigir

Mascarar o sintoma no proxy quase pareceu suficiente. Mas mascarar deixa o RCE no lugar. Ele continua explorável até a causa ser corrigida.

Um grep limpo não é o sinal de tudo certo

Mesmo sem nenhuma chave em arquivo algum, uma vulnerabilidade pode extrair variáveis de ambiente de um processo em execução. Vazamentos acontecem em tempo de execução (RCE, headers HTTP), não só em arquivos. Veja O que é RCE.

A causa real: um CVSS 10.0 publicado e deixado sem correção

Uma assinatura estranha em logs de acesso antigos logo casou com a inteligência de ameaças. A faixa de versões do framework web em uso tinha um RCE pré-autenticação publicado (CVSS 10.0) que já estava sendo explorado na prática — e ficou sem correção por meses.

  • Isso não foi um bug passivo — foi um invasor executando código no servidor e exfiltrando o ambiente.
  • Uma coisa limitou o dano: a execução ficou dentro de um container sem privilégios (o root do host não foi tomado). A análise da invasão não encontrou backdoor persistente, minerador nem C2 — o impacto confirmado foi o roubo de segredos.
  • Como o banco de dados interno estava acessível, a resposta presumiu que o conteúdo do banco também havia vazado.
Sintoma visível: uma fatura surpresa e irreconhecível
isto é tudo o que o dono consegue ver
↑ chaves roubadas são revendidas / abusadas depois
todo o env (cada segredo) é exfiltrado
↑ o invasor executa código arbitrário no servidor em produção
causa: um CVSS 10.0 publicado e deixado sem correção (RCE pré-autenticação)
A fatura surpresa é apenas o sintoma visível. Por baixo dela está a causa: um CVSS 10.0 publicado e deixado sem correção.

Lição: quando algo se comporta de forma estranha, suspeite primeiro de um CVE conhecido. Não presuma que é um bug seu.

Restrinja o vazamento: onde essa chave estava?

Quando o grep não encontra nada, mude a forma de procurar. Liste onde a chave abusada estava escrita, e os caminhos de vazamento candidatos diminuem. Se a chave abusada só existia nas variáveis de ambiente do servidor de produção, por exemplo, suspeite do servidor de produção ou do provedor de hospedagem, não do Git nem do navegador.

Onde vazaCausa comumComo verificar a sua configuraçãoComo fechar
Histórico do Git / repositórios públicosCommitar o .env, chaves escritas direto no códigoVarra todo o histórico com gitleaks git. Confira os alertas de secret scanning do GitHubRevogue primeiro, depois bloqueie antes do commit
JavaScript enviado ao navegadorUma chave numa variável NEXT_PUBLIC_, chamar a API direto do navegadorProcure o prefixo da chave na saída do buildMova a chamada à API para código do lado do servidor
Uma pasta web pública.env ou backups colocados na pasta públicaAbra /.env no seu próprio site e confirme que retorna 404 ou 403Mova os arquivos secretos para fora da pasta pública
Logs / páginas de erroPublicar com a saída de debug ativada, registrar headers de requisição como estãoConfira as configurações de debug em produção e se Authorization e similares aparecem nos logsDesative a saída de debug e mascare segredos nos logs
O servidor em execuçãoUma vulnerabilidade publicada (como um RCE) deixada sem correçãoCompare a versão de fato em execução com a versão corrigida no aviso de segurançaAtualize e depois substitua todos os segredos do ambiente
O provedor de hospedagemUma invasão do lado do provedorConfira os boletins de segurança e os avisos por e-mail do provedorGuarde os segredos de forma que os valores não possam ser vistos depois, e rotacione
Sua máquina de desenvolvimentoUm pacote ou extensão maliciosoVerifique se as versões de pacotes ou extensões que você instalou coincidem com um comprometimento publicadoRemova essa versão e substitua os segredos que estavam na máquina

Este caso foi a linha "o servidor em execução". As quatro linhas de baixo são caminhos que não deixam rastro no seu código nem no Git. O Secrets Management Cheat Sheet da OWASP também alerta que as variáveis de ambiente costumam ser legíveis por outros processos no mesmo ambiente e podem acabar em logs ou dumps. Então, quando uma chave é abusada, trate como vazados todos os segredos guardados no mesmo lugar.

Chaves separadas aceleram a investigação

Se você usa uma chave diferente por serviço e por ambiente (produção vs. desenvolvimento), só a chave abusada já diz em qual linha da tabela você está. Reutilize uma única chave em todo lugar e você terá de suspeitar de todos os locais. Como separar as chaves é explicado em Quando uma chave de API roubada faz sua conta da OpenAI ser banida.

Conte as vulnerabilidades pela versão que de fato está rodando

Ao verificar as outras dependências, "mais 8 dependências vulneráveis" foi reportado. Isso também estava errado. Tinham sido contadas pelo piso no package.json (a faixa com o acento circunflexo ^). As realmente perigosas eram apenas as 2 dependências fixadas que ficaram para trás.

Confira suas próprias versões em execução

Veja as versões de fato resolvidas, no lockfile ou no container em execução.

# npm: see what's actually installed
npm ls next react react-dom
 
# inside a running container
docker exec <container> npm ls <package>

Os números aqui são as versões que de fato estão rodando, não o ^ no package.json.

Como verificar a sua própria configuração

Quer você tenha acabado de notar uma fatura estranha, quer nada tenha acontecido ainda, dá para verificar nesta ordem. Cada passo só olha a sua própria conta e o seu próprio servidor.

1

Veja qual chave foi usada, e quando

No painel da API de IA, separe o uso e o custo por projeto (na Anthropic, por Workspace) e por dia. Uso em modelos que você nunca usa, ou em horários em que nada seu roda, significa que essa chave vazou. Depois, comece pela linha da tabela correspondente ao lugar onde essa chave estava guardada.
2

Confira os arquivos enviados ao navegador

No Next.js, os valores das variáveis de ambiente que começam com NEXT_PUBLIC_ são embutidos no momento do build no JavaScript enviado ao navegador. Depois de um build, procure o prefixo da sua chave na saída, por exemplo grep -rl "sk-" .next/static. Qualquer coisa encontrada ali estava legível para qualquer pessoa.
3

Confirme que os arquivos secretos não são acessíveis pela pasta pública

Rode curl -sI https://example.com/.env contra o seu próprio site (troque example.com pelo seu domínio) e confirme que o status na primeira linha não é 200 (deve ser 404 ou 403). Mais em auditando arquivos secretos em diretórios públicos.
4

Compare a versão em produção com o aviso de segurança

Como no quadro acima, rode npm ls dentro do container de produção para ver a versão. osv-scanner scan -L pnpm-lock.yaml verifica se o seu lockfile inclui versões com vulnerabilidades conhecidas.
5

Procure segredos nos logs

Rode gitleaks dir --redact na pasta onde ficam os logs do seu app para encontrar chaves escritas nos logs. O --redact mantém os próprios valores encontrados fora da tela.
6

Confira limites e alertas

A OpenAI permite configurar alertas de gastos e um limite rígido mensal de gastos na página de limites do painel. A Anthropic permite configurar um limite de gastos por Workspace. Garanta que você não tem só alertas que nunca param nada.

O que foi feito primeiro (passos reproduzíveis)

1

Revogar a chave abusada imediatamente

Interrompe o dano, mas é só parte do trabalho.
2

Atualizar o framework para a versão corrigida

Fechar o RCE de verdade. Após atualizar, confirme que a assinatura do vazamento some nos logs.
3

Rotacionar todos os segredos

Suponha-os vazados. Ordene por "abusável de qualquer lugar primeiro": chaves de object storage → chave de assinatura de sessão → chaves de API → credenciais do banco.
4

Análise da invasão

Verifique persistência, cron malicioso, C2 de saída (nada aqui).
5

Defesa do lado da conta

Troque a senha, ative MFA, verifique chaves de API desconhecidas.

Prevenção: monitore CVEs automaticamente

Resumindo, este incidente foi "um humano deixou passar um CVSS 10.0 publicado". Verificações manuais sempre deixam algo escapar. O monitoramento automático os detecta.

Varredura de dependências que você pode começar hoje

Grátis para começar — um passo no CI.

# OSV scanner (Google) checks your lockfile
osv-scanner scan -L pnpm-lock.yaml
 
# On GitHub, enable Dependabot (repo Settings → Security)

Este site, seguindo esta própria lição, monitora suas dependências em busca de CVEs — praticamos o que recomendamos.

Erros comuns e como corrigi-los

  • Colocar uma chave nova num servidor que continua aberto: o mesmo caminho rouba a chave nova também. Pare a chave abusada na hora, corrija a vulnerabilidade e só então termine de substituir os segredos restantes.
  • Tratar um alerta de orçamento como teto: o Google Cloud afirma que um orçamento só com alertas não para automaticamente o uso nem os gastos. Se você quer que pare, acrescente um limite que bloqueie o uso, como o limite rígido mensal da OpenAI ou um limite de gastos de Workspace da Anthropic.
  • Colocar uma chave de API de IA num navegador ou app móvel: qualquer valor que chega ao dispositivo do usuário pode ser extraído. Chame a API de IA a partir do seu servidor e faça o navegador chamar o seu servidor.
  • Apagar dos arquivos ou do histórico do Git e parar por aí: quem já copiou ainda pode usar. Revogue primeiro, limpe o histórico depois (veja por que credenciais vazadas no GitHub continuam válidas, em inglês).
  • Usar a mesma chave em desenvolvimento e produção: você não consegue saber qual lado vazou e precisa parar os dois. Emita uma chave separada por ambiente.

Um exemplo público: variáveis de ambiente vazadas do lado do provedor

Vazamentos que nenhuma busca em arquivos encontra também acontecem fora do seu próprio servidor. Em 19 de abril de 2026, a Vercel divulgou um acesso não autorizado aos seus sistemas internos. Segundo a empresa, o comprometimento de uma ferramenta de IA de terceiros usada por um funcionário levou ao roubo de variáveis de ambiente de alguns clientes que não estavam marcadas como "sensitive" (a configuração que torna um valor impossível de visualizar depois de salvo).

A Vercel orientou os clientes a revisar e rotacionar as variáveis de ambiente não marcadas como sensitive e a conferir os logs de atividade e os deploys recentes. Também afirmou que apagar projetos ou a conta não basta para eliminar o risco.

Clientes nessa situação poderiam procurar no código e no Git o dia todo sem achar rastro de vazamento. A ação é a mesma deste caso: substituir todos os segredos guardados naquele lugar. Os passos estão em o incidente de segurança da Vercel (abril de 2026) (em inglês).

Lições

Erros comuns

  • Considerar resolvido em "parou as cobranças"
  • Relaxar porque o grep está limpo
  • Mascarar o sintoma num proxy e achar que corrigiu
  • Contar vulnerabilidades pelo piso do package.json
  • Rotacionar só a única chave confirmadamente abusada

Defesa correta

  • Tratar a interrupção das cobranças e o fechamento do caminho do vazamento como dois trabalhos separados, e fazer ambos
  • Suspeitar também de vazamentos em tempo de execução (RCE, headers)
  • Atualizar o framework que causou o problema
  • Julgar pela versão de fato em execução
  • Substituir todo o env se ele vazar

Resumindo: o pico na fatura era um sintoma, e a causa foi um RCE CVSS 10.0 deixado sem correção. A causa correta não foi encontrada na primeira tentativa; foi encontrada errando várias vezes e verificando de novo.

Leia a seguir

Fontes

  • OWASP, "Secrets Management Cheat Sheet" (riscos das variáveis de ambiente, resposta a vazamentos): cheatsheetseries.owasp.org
  • Documentação do Next.js, "How to use environment variables in Next.js" (embutimento de NEXT_PUBLIC_): nextjs.org
  • OSV-Scanner, "Usage": google.github.io
  • OpenAI, "Production best practices" (manejo de chaves, alertas e limites): developers.openai.com
  • Central de Ajuda do Claude, "Creating and managing Workspaces" (limites e chaves de Workspace): support.claude.com
  • Google Cloud, "Create, edit, or delete budgets and budget alerts": docs.cloud.google.com
  • Vercel, "Vercel April 2026 security incident": vercel.com

FAQ

QSe uma chave de API vaza, basta revogar apenas a chave que foi abusada?
A

Não. Quando o caminho do vazamento é em tempo de execução (um RCE ou um vazamento por header), suponha que todos os segredos do ambiente vazaram de uma vez e rotacione todos. A chave que você viu sendo abusada é só uma pequena parte do que vazou.

QSe um grep no meu código e no git não encontra nenhuma chave, estou seguro?
A

Não necessariamente. Mesmo sem nenhuma chave em arquivo algum, uma vulnerabilidade no framework pode exfiltrar variáveis de ambiente direto do processo em execução. Vazamentos também acontecem em tempo de execução, não só em arquivos.

QO que impede isso de acontecer de novo, da forma mais confiável?
A

Monitorar suas dependências em busca de CVEs por máquina. A causa aqui foi um humano deixando passar um CVSS 10.0 publicado por meses; o Dependabot ou o osv-scanner detectam isso automaticamente.

QA fatura da minha API de IA disparou de repente. O que faço primeiro?
A

Primeiro, desative a chave abusada no painel do provedor para interromper o dano. Depois, restrinja o caminho do vazamento a partir de onde essa chave estava guardada, corrija a vulnerabilidade ou a configuração errada e só então substitua todos os segredos que estavam no mesmo lugar. Revogar só a chave deixa o caminho do vazamento aberto.

QComo descubro qual chave vazou?
A

No painel da API de IA, separe o uso e o custo por projeto (na Anthropic, por Workspace). A chave por trás de uso em modelos ou em horários que você nunca usa é a que vazou. Se você mantém chaves separadas por serviço e ambiente, o lugar onde essa chave estava guardada também indica o caminho do vazamento.

QSe eu configurar um alerta de orçamento, as cobranças fraudulentas param?
A

Não necessariamente. O Google Cloud, por exemplo, afirma que um orçamento só com alertas não limita automaticamente o uso nem os gastos. Para de fato parar o uso, configure um limite que o bloqueie, como o limite rígido mensal de gastos da OpenAI ou um limite de gastos por Workspace na Anthropic.