Pular para o conteúdo
Ícones de chaves digitais e cadeados com código binário vazando de um repositório GitHub, representando credenciais expostas e vulneráveis.
Voltar para o Blog

543 Mil Chaves Vazadas no GitHub Ainda Funcionam: Por Que Apagar o Commit Não Resolve e o Passo a Passo Para Revogar

Equipe Golber.
8 min de leitura
Segurança

Entre na sua conta para curtir e guardar o que gostou.

Ouça este artigo

543 Mil Chaves Vazadas no GitHub Ainda Funcionam: Por Que Apagar o Commit Não Resolve e o Passo a Passo Para Revogar

0:00 / 12:41
1×
Sincronia do destaque
no ponto
Se a voz parecer atrás do trecho marcado, atrase o destaque
Ícones de chaves digitais e cadeados com código binário vazando de um repositório GitHub, representando credenciais expostas e vulneráveis.

Um estudo achou 543 mil credenciais em repositórios públicos do GitHub que ainda funcionavam, e 88% das senhas de Postgres sobreviveram. Por que apagar o commit não resolve, o que o bloqueio do GitHub não pega e o caso que escapou da minha trava.

Das URLs de conexão do Postgres esquecidas em repositórios públicos do GitHub, 88% ainda abriam o banco quando alguém foi testar. É o que mostra um estudo da Truffle Security publicado em 29 de setembro: das credenciais encontradas em repositórios públicos, 543.699 ainda funcionavam quando foram testadas, em julho de 2026. Metade delas estava exposta havia mais de dois anos.

A lição do estudo não é "cuidado para não subir chave". É outra, e mais útil: apagar o commit não resolve, e o bloqueio do GitHub não pega os segredos mais perigosos. Abaixo estão os números, o que eu faço no golber.net, um caso real que escapou da minha própria trava e o passo a passo para quando acontecer com você.

  • Os números do estudo e quais chaves sobrevivem

  • Por que apagar o commit não revoga nada

  • O que o bloqueio do GitHub não pega

  • Os quatro passos quando uma chave vaza

  • Como travar no commit, e o caso que escapou

543 mil chaves que ainda funcionam

A Truffle Security, a empresa que mantém o TruffleHog, varreu 224 milhões de repositórios públicos e testou cada credencial encontrada no próprio serviço que a emitiu. 543.699 autenticaram. A exposição mediana era de 784 dias, um quarto tinha mais de quatro anos e a mais antiga, de 2009, funcionou 16 anos depois.

O que sobrevive depende de quem é o dono da chave. Os números do relatório da Truffle mostram isso com clareza:

Tipo de credencial

Encontradas

Ainda funcionando

Postgres (URL de conexão)

12.985

11.465 (88%)

MySQL

2.421

1.806 (75%)

Conta de serviço do Google Cloud

126.963

69.041 (54%)

SendGrid

22.800

9.189 (40%)

AWS

82.411

6.819 (8%)

Stripe

124.132

4.493 (4%)

Token do GitHub

73.048

260 (0,36%)

Token do npm

101.886

1

O padrão é óbvio depois de visto. GitHub e npm revogam os próprios tokens quando os encontram expostos, e quase nada sobrevive. Ninguém revoga a URL do seu Postgres, e quase tudo sobrevive. A frase da Truffle resume: "What keeps a leaked credential alive is revocation, not the block at push time".

Dois números chamam atenção para quem trabalha com IA. Das chaves Google ativas, 31.374 funcionam no Gemini. E a densidade de credenciais vivas por milhão de arquivos triplicou de 2014 para 2025, quando bateu o recorde do levantamento.

Apagar o commit não revoga nada

Apagar o arquivo, reescrever o histórico ou até apagar o repositório tira a chave de onde ela foi achada, mas a chave continua valendo. Ela segue em clones, forks e páginas em cache do GitHub. A documentação do próprio GitHub manda, como primeiro passo, revogar ou trocar o segredo, e diz que reescrever o histórico depois disso pode nem ser necessário.

O estudo tem uma ironia que prova o ponto: as chaves foram achadas num dataset montado para treinar modelos de IA. Quando você sobe uma senha, ela não fica só no seu repositório. Ela é copiada para espelhos, forks e conjuntos de dados que você nunca vai ver.

Chave vazada não se apaga. Se revoga. Todo o resto é limpeza.

O que o bloqueio do GitHub não pega

O GitHub bloqueia por padrão, desde fevereiro de 2024, o envio de vários tipos de chave para repositório público, e varre o histórico de graça. Mas o bloqueio só vale para chaves com formato conhecido. URL de conexão de banco, chave privada e chave do Google e do Gemini ficam de fora, e são 51,8% das credenciais vivas do estudo.

Pela lista oficial de padrões, chaves da OpenAI, da Anthropic, da AWS, do Stripe e do Resend são bloqueadas no envio. A chave do Gemini não é. E mesmo nas bloqueadas, dá para ignorar o aviso e enviar assim mesmo. O efeito aparece nos números: 36,8% das credenciais vivas são de depois do bloqueio padrão.

A conta de quem esquece uma chave de IA pode ser alta. Em fevereiro, uma startup mexicana de três desenvolvedores teve uma chave do Google usada no Gemini por 48 horas e recebeu US$ 82.314 de cobrança, contra um gasto normal de US$ 180 por mês, segundo o The Register. A matéria não diz como a chave vazou, mas mostra o tamanho do estrago possível.

Os quatro passos quando uma chave vaza

Primeiro revogue, depois investigue, só então limpe. Perguntei ao Jev qual é a primeira coisa que um dev deve fazer ao achar a senha do banco de produção num repositório público. Ele deu 98% para revogar e trocar a credencial no provedor, e 1% para apagar o histórico. Está certo, e é a mesma ordem da OWASP.

  1. Revogue e troque no provedor. Gere a nova chave, atualize o servidor e só então desative a antiga, para não derrubar o sistema. Banco de dados: troque a senha do usuário. Nuvem: desative a chave de acesso.

  2. Audite o uso. Olhe os logs e a cobrança do período em que a chave ficou exposta. Na AWS, a quarentena automática não bloqueia tudo, então confira.

  3. Limpe o histórico. O GitHub recomenda o git-filter-repo com a opção --sensitive-data-removal, depois tratar forks e pedidos de pull e, se precisar, abrir chamado no suporte.

  4. Previna. Ponha uma trava no commit, prefira credenciais que expiram sozinhas e mantenha o .env fora do repositório.

Para descobrir se você tem alguma chave exposta, rode o TruffleHog no repositório com --results=verified: ele testa cada candidata no provedor e mostra só as que funcionam. O gitleaks, com gitleaks git -v, varre o histórico inteiro pelo formato. E no repositório público, a aba de segurança do GitHub mostra os alertas da varredura gratuita.

Trava no commit, e o caso que escapou

No golber.net, todo commit passa por um hook que roda o gitleaks antes de gravar: se ele acha algo com cara de segredo, o commit é recusado. As chaves ficam num cofre fora do repositório, e o repositório é privado. Mesmo assim, em setembro, um segredo de produção escapou dessa trava.

Foi assim. Um script gerado com ajuda de IA usou o valor real de um segredo interno, o que autoriza a publicação agendada dos posts, como valor padrão dentro do código. O gitleaks não pegou, porque o valor não tinha o formato de nenhuma chave conhecida. Era só uma sequência de caracteres. O segredo foi trocado em 20 de setembro, e o repositório nunca foi público.

É exatamente o ponto cego do estudo: segredo genérico passa por qualquer ferramenta que procura formato. E a IA aumenta o risco. O relatório da GitGuardian de 2026 mediu 3,2% de vazamento em commits feitos com ajuda do Claude Code, contra 1,5% na média, e os segredos de serviços de IA expostos cresceram 81% em um ano. Já escrevi que programar com IA não é copiar e colar; segredo no código é o exemplo mais caro disso.

Três regras que esse caso ensina:

  • Valor padrão de segredo no código é proibido, mesmo em script descartável. Sem a variável de ambiente, o script tem de falhar.

  • Revisar o diff de código gerado por IA procurando string longa que não é texto.

  • Ter o caminho de troca de cada segredo escrito antes de precisar: onde mora, quem usa, como trocar sem derrubar.

Isso entra na rotina de segurança que descrevi no post sobre ameaças e patches para dev solo, e vale para quem usa agente de código no dia a dia, como mostrei nos prós e contras do Claude Code. Software sem correção também é porta aberta, como no caso do PHP 8.2 sem suporte.

As apostas, com a probabilidade do Jev, escritas pelo lado que ele acha mais provável. Eu confiro em janeiro e o resultado vai para o placar público das previsões:

ApostaConfiançaVerificaçãoResultado
Até 31/12/2026, o push protection do GitHub continua sem bloquear por padrão a chave do Gemini e as Google API keys.77%05/01/2027Em aberto
Até 31/12/2026, o push protection do GitHub continua sem bloquear por padrão URLs de conexão de banco de dados.81%05/01/2027Em aberto
Até 31/12/2026, nem a Truffle nem o GitHub publicam quantas das 543.699 credenciais foram revogadas depois do estudo.87%05/01/2027Em aberto
Até 31/12/2026, o GitHub não divulga o total de segredos vazados na plataforma em 2025.65%05/01/2027Em aberto

Se você quer alguém olhando o seu projeto com esse cuidado, procurando segredo no código, no histórico e na configuração do servidor, é parte do que eu entrego no diagnóstico técnico do site.

Perguntas frequentes

Como saber se minha chave de API vazou no GitHub?

Rode o TruffleHog no repositório com a opção que testa cada chave no provedor, ou o gitleaks para varrer o histórico pelo formato. Em repositório público, veja também os alertas na aba de segurança do GitHub, que varre o histórico de graça.

Apaguei o commit. A chave ainda está exposta?

Sim. Ela continua em clones, forks e páginas em cache, e apagar não revoga nada. A única correção é revogar ou trocar a chave no provedor. Limpar o histórico vem depois.

Como remover uma senha do histórico do git?

Primeiro troque a senha. Depois use o git-filter-repo com a opção de remoção de dados sensíveis, como recomenda o GitHub, avise quem tem fork e, se necessário, peça ajuda ao suporte para limpar o cache.

O GitHub avisa se eu subir uma chave?

Em parte. O bloqueio padrão pega chaves com formato conhecido, como as da OpenAI, da AWS e do Stripe, mas dá para ignorar o aviso. URL de banco, chave privada e chave do Gemini não são bloqueadas por padrão.

Subi meu .env para o GitHub. O que eu faço?

Troque todas as credenciais que estavam no arquivo, confira logs e cobrança do período, depois limpe o histórico e ponha o .env no .gitignore. Um hook de pre-commit com o gitleaks evita a repetição.

Gostou?
Compartilhar

Golber Dóriaquem escreve este blog

Receba os posts novos no seu email

IA aplicada ao trabalho, stack e o negócio de uma pessoa só, direto na sua caixa de entrada. Sem spam, e sair é um clique em qualquer email.