Chave vazada no GitHub

O que fazer quando uma chave de API vai parar no GitHub: como a proteção de envio funciona, como resolver um envio bloqueado e a ordem certa se a chave já subiu.

  • GitHub
  • conferido na documentação oficial
  • exemplos com chave falsa

Publicado em

O que aconteceu

Uma chave de API é uma senha que um serviço (de IA, pagamento, e-mail ou nuvem) entrega para o seu programa usar a sua conta. Quem tem a chave age como você naquele serviço.

A chave "vaza" quando vai parar num lugar que outras pessoas conseguem ver. O caso mais comum é escrever a chave no código e enviar o projeto para um repositório público no GitHub sem perceber.

A documentação do GitHub diz que qualquer segredo vazado deve ser considerado comprometido imediatamente, e que scanners automáticos conseguem encontrar segredos expostos publicamente em minutos.

Por isso este guia tem duas partes: o que o GitHub faz para barrar o envio antes de a chave sair do seu computador e o que fazer, na ordem certa, se ela já saiu.

Quatro palavras que aparecem ao longo do guia (explicação geral de Git, fora da documentação do GitHub):

  • Repositório: a pasta do projeto guardada no GitHub.
  • Commit: um registro salvo do projeto, uma foto dos arquivos naquele momento.
  • Push (envio): o comando git push, que manda os seus commits para o repositório no GitHub.
  • Histórico: a lista de todos os commits. Cada commit guarda uma versão dos arquivos.

Todas as chaves deste guia são falsas e aparecem como sk-EXEMPLO-.... O que vem da documentação do GitHub aparece sem marcação. O que é recomendação do guia vem marcado como "Recomendação do guia".

A proteção de push do GitHub

A proteção de push (push protection) confere o que você está enviando. Se encontra um segredo, bloqueia o envio e mostra uma mensagem com o motivo.

Para usuários, ela vem ativada por padrão em repositório público. A documentação a descreve como específica da sua conta do GitHub e disponível no GitHub.com.

O que ela faz

  • Bloqueia o envio quando encontra um segredo com padrão reconhecido, e mostra uma mensagem com o motivo.
  • Vem ativada por padrão para usuários, em repositório público.
  • Vale para a sua conta do GitHub.

O que ela não promete

  • Pegar qualquer chave ou senha: a documentação descreve o bloqueio para credenciais de provedores com suporte.
  • Funcionar em repositório privado: a documentação consultada não diz nada sobre isso.
  • Apagar uma chave que já foi enviada: a página descreve o bloqueio no momento do envio.

A mesma página descreve outros tipos de detecção (padrões genéricos, personalizados e detecção por IA), mas não diz que a proteção do usuário cobre todos eles. Os padrões genéricos, por exemplo, precisam estar ativados nas configurações de segurança do repositório.

Onde conferir na sua conta

  1. No canto superior direito de qualquer página do GitHub, clique na sua foto de perfil e depois em Settings.
  2. Na seção Security da barra lateral, clique em Code security.
  3. Em User, ao lado de "Push protection for yourself", confira se a proteção está ativada.

Dica

Recomendação do guia: se o GitHub não bloqueou o envio, não conclua que a chave está segura. A proteção reconhece padrões de provedores com suporte e pode não reconhecer o da sua chave. Mantenha a chave fora do código desde o começo.

Se o envio foi bloqueado

Quando você roda git push e o GitHub encontra um segredo, o envio não é concluído e o terminal mostra uma mensagem com o motivo. Ela lista todos os commits que contêm o segredo. Na página oficial, cada item aparece em locations, com o commit e o path (arquivo e linha) onde o segredo está.

A regra da documentação: para resolver um envio bloqueado, você precisa remover o segredo de todos os commits em que ele aparece. Tirar a chave só do arquivo atual não resolve se ela continua num commit mais antigo da mesma sequência.

Nota

Recomendação do guia: se você também colou a chave em outro lugar (mensagem, print ou outro repositório), trate-a como vazada e vá direto para a seção "Se a chave já subiu: a ordem certa".

Parte A: tire a chave do código

Recomendação do guia: guarde a chave num arquivo .env, que fica só no seu computador, e leia o valor no código por variável de ambiente. A documentação do GitHub recomenda usar variáveis de ambiente em vez de escrever o segredo no código.

arquivo .env, fica só no seu computador
API_KEY=sk-EXEMPLO-...
JavaScript, errado: a chave escrita no código
const apiKey = 'sk-EXEMPLO-...';
JavaScript, certo: a chave vem da variável de ambiente
const apiKey = process.env.API_KEY;
Python, certo: a chave vem da variável de ambiente
import os

api_key = os.environ["API_KEY"]

Muitas ferramentas leem o .env sozinhas. Nas outras, uma biblioteca que carrega arquivos .env resolve. Confira a documentação da sua ferramenta.

Agora impeça o Git de guardar o .env. A página do GitHub sobre arquivos ignorados diz que você pode criar um arquivo .gitignore na raiz do repositório. Crie o arquivo com esta linha:

arquivo .gitignore
.env

Se o .env já tinha entrado no Git, só o .gitignore não basta. A mesma página diz que, para ignorar um arquivo que já está registrado, você precisa antes tirá-lo do controle do Git:

terminal
git rm --cached .env

Parte B: tire a chave dos commits

Se a chave entrou no último commit da sua branch, atualize esse commit em vez de criar um novo. O comando abaixo atualiza o commit original:

terminal, segredo no último commit
git commit --amend --all
git push

Nota

Explicação geral de Git: o git commit --amend abre um editor de texto com a mensagem do commit. Salve e feche o editor para continuar. Se não quiser mudar a mensagem, não altere o texto.

Dica

Recomendação do guia: o --all só inclui arquivos que o Git já acompanha. Se você acabou de criar o .gitignore, rode git add .gitignore antes do git commit --amend --all.

Se a chave entrou num commit anterior, descubra qual é o mais antigo que a contém. A mensagem de erro lista os commits e o git log mostra o histórico da branch, com as datas:

terminal
git log

Com o identificador (ID) do commit mais antigo que contém a chave, comece um rebase interativo. Explicação geral de Git: o ~1 faz o rebase começar um commit antes dele.

terminal, troque ID-DO-COMMIT pelo ID real
git rebase -i ID-DO-COMMIT~1

No editor que abrir, troque pick por edit na primeira linha, a do commit que você identificou. Salve e feche o editor. Depois remova a chave do código e rode:

terminal
git add .
git commit --amend
git rebase --continue
git push

Nota

Existe um espaço entre add e .. O ponto faz parte do comando.

Atenção

Não existe atalho seguro para um envio bloqueado. O caminho é tirar a chave de todos os commits em que ela aparece.

Se a chave já subiu: a ordem certa

Se a chave chegou ao repositório, apagar o arquivo não resolve. A documentação do GitHub diz que remover o segredo do código, enviar um commit novo ou apagar e recriar o repositório não impede que o segredo seja explorado.

Explicação geral de Git: o histórico guarda cada versão do projeto. Se um commit antigo contém a chave, quem abrir esse commit consegue ver. A documentação diz que o segredo pode continuar no histórico de commits do repositório.

A ordem abaixo segue a do tutorial oficial do GitHub sobre como remediar um segredo vazado:

  1. Revogue ou troque a chave no serviço que a emitiu.
  2. Confira se houve uso indevido, no painel do provedor.
  3. Limpe o histórico com git-filter-repo, com cuidado.

Nota

O tutorial oficial tem outras etapas, como identificar o segredo, avaliar o risco e fechar o alerta. Este guia cobre três delas: revogar, conferir e limpar.

Passo 1: revogue ou troque a chave no serviço que a emitiu

Revogar é invalidar a chave, para que ela pare de funcionar. Trocar (rotacionar) é gerar uma chave nova no lugar dela. Segundo a documentação, revogar o segredo no provedor dele é o passo de remediação mais importante, e remover o segredo do código não é suficiente.

A página sobre remoção de dados sensíveis diz que, depois que o segredo é revogado ou trocado, ele não pode mais ser usado para acesso.

Faça isso no painel do serviço que emitiu a chave. Os nomes dos menus mudam de serviço para serviço. Procure a área de chaves de API, tokens ou credenciais e siga a instrução de revogação do próprio provedor. Se você não tem acesso ao painel, peça a quem é dono da chave ou administra o repositório.

Avise também o dono da chave e quem administra o repositório, como a documentação recomenda.

Se a chave está em uso em produção

Revogar de uma vez pode derrubar a aplicação. Quando a queda é uma preocupação, a documentação sugere esta ordem: gerar a nova chave primeiro, com as mesmas permissões, fazer a aplicação usar a nova e só então revogar a antiga.

  1. Gere a chave nova no provedor, com as mesmas permissões da antiga.
  2. Atualize a aplicação e os outros serviços que usavam a antiga e confirme que eles usam a nova.
  3. Revogue a chave antiga.

Atenção

Não deixe a chave antiga ativa além do necessário. A mesma página manda priorizar a revogação imediata do segredo.

E se o próprio GitHub já revogou?

A documentação diz que o GitHub revoga automaticamente os tokens de acesso pessoal (PAT) do GitHub que vazam em repositório público. Para segredos de provedores parceiros que vazam em público, o GitHub avisa o provedor, que pode agir.

Dica

Recomendação do guia: não espere por isso. Revogue você mesmo e confirme no painel que a chave antiga deixou de funcionar.

Passo 2: confira se houve uso indevido

Uma chave exposta pode ter sido usada antes de você revogá-la. A documentação manda checar se houve acesso não autorizado enquanto o segredo esteve exposto. No tutorial, essa etapa vem depois de revogar e atualizar a chave.

  • No painel ou nos registros de auditoria do provedor da chave. A documentação cita o AWS CloudTrail como exemplo de registro que mostra se uma credencial vazada foi usada.
  • Nos registros do GitHub: o log de segurança da sua conta pessoal ou o log de auditoria da organização, procurando eventos ligados ao segredo. O seu papel define o que você consegue ver.

Dica

Recomendação do guia: procure uso em horários em que você não usou o serviço, consumo ou cobrança acima do normal e recursos ou chaves que você não criou. Se achar algo assim, fale com o suporte do provedor.

Passo 3: limpe o histórico, com cuidado

Mesmo com a chave revogada e trocada, ela pode continuar no histórico de commits. A documentação diz que, idealmente, você deve procurar e remover todas as ocorrências do segredo no repositório.

Nota

Limpar é o ideal, mas revogar pode bastar. A página oficial de remoção diz que, depois que o segredo é revogado ou trocado, isso pode ser suficiente para resolver o problema.

Atenção

Limpar o histórico reescreve o histórico e afeta quem tem cópia do repositório. A documentação o descreve como um processo destrutivo e que atrapalha quem trabalha no projeto, e que envolve forçar o envio (force push) para o repositório. A página de remoção diz que o histórico pode ser limpo se você coordenar com cuidado com todas as pessoas que clonaram o repositório.

A ferramenta que a documentação usa é o git-filter-repo. É preciso uma versão com a opção --sensitive-data-removal, ou seja, a versão 2.47 ou mais. A página mostra a instalação com Homebrew:

terminal, exemplo da página com Homebrew
brew install git-filter-repo

Em outro sistema, procure as instruções de instalação do git-filter-repo e confira se a versão instalada é a 2.47 ou mais.

Clone o repositório numa pasta nova e entre nela. Troque pelos seus dados:

terminal
git clone https://github.com/SEU-USUARIO/SEU-REPOSITORIO
cd SEU-REPOSITORIO

Para apagar de todo o histórico um arquivo que continha a chave, como o .env, use o caminho dele no Git:

terminal
git-filter-repo --sensitive-data-removal --invert-paths --path .env

Se o arquivo já foi movido ou renomeado alguma vez, a página manda repetir o --path para cada caminho antigo ou rodar o comando de novo. Para trocar um texto dentro de arquivos em vez de apagar o arquivo, ela mostra a opção --replace-text com um arquivo de lista. A página não detalha o formato desse arquivo, então consulte o manual do git-filter-repo antes de usar.

Confira o resultado antes de enviar. A página manda verificar que tudo o que você queria remover sumiu, mas não explica como. Recomendação do guia: procure o começo da chave em todo o histórico. O comando não deve mostrar nenhum commit. Explicação geral de Git: o -S procura commits em que o texto informado foi adicionado ou removido, e o --all olha todas as branches e tags. Troque sk-EXEMPLO- pelo começo da sua chave:

terminal, recomendação do guia
git log --all --oneline -S"sk-EXEMPLO-"

O próximo passo não tem volta. Quando tiver certeza, envie a versão limpa para o GitHub, sobrescrevendo o repositório:

terminal
git push --force --mirror origin

Envios para refs/pull/ vão falhar, e isso é esperado, porque o GitHub marca essas referências como somente leitura. Se outras referências falharem, a página diz que provavelmente há proteção de branch ligada naquela branch.

Atenção

O --force descarta mudanças que outras pessoas tenham feito nessas referências enquanto você limpava o repositório.

Depois da limpeza, avise quem tem cópia

  • Quem clonou antes da reescrita ainda tem os dados antigos. A página manda descartar o clone e clonar de novo.
  • Quem rodar git pull e depois git push com uma cópia antiga pode trazer a chave de volta.
  • Quem criou branches a partir do histórico antigo deve fazer rebase, e não merge. Um merge pode reintroduzir o histórico que você acabou de limpar.

O que a limpeza não alcança

Segundo a documentação, se você só reescreve o histórico e faz o envio forçado, os commits com o dado sensível ainda podem estar acessíveis em outros lugares:

  • Em qualquer clone ou fork do repositório.
  • Diretamente pelo hash SHA-1 do commit, em visualizações em cache no GitHub.
  • Em pull requests que referenciam esses commits.

Você não consegue remover os dados dos clones de outras pessoas. Se o commit existe em algum fork, ele continua acessível lá, e o GitHub não pode fornecer o contato dos donos desses forks. As visualizações em cache e as referências em pull requests podem ser removidas de forma permanente, e isso passa pelo Suporte do GitHub.

O Suporte do GitHub só ajuda com dados sensíveis, e apenas quando considera que o risco não pode ser reduzido trocando as credenciais afetadas. Leitura do guia, fora da documentação: é a revogação do passo 1 que protege você. A limpeza reduz a exposição, mas não apaga todas as cópias.

Como evitar que aconteça de novo

A documentação do GitHub diz que o foco com segredos deve ser evitar o vazamento. Estas práticas ajudam.

Chave fora do código e `.env` fora do Git

Guarde a chave num arquivo .env, ignorado pelo Git com o .gitignore, e leia o valor por variável de ambiente, como na parte A da seção "Se o envio foi bloqueado". A documentação recomenda usar variáveis de ambiente em vez de escrever segredos no código.

Recomendação do guia: crie também um .env.example, com os nomes das variáveis e valores de mentira, para quem usar o projeto saber o que preencher. Esse arquivo pode ir para o Git.

arquivo .env.example, pode ir para o Git
API_KEY=cole-a-chave-aqui

A documentação também recomenda trocar os segredos com regularidade, para reduzir o impacto de um vazamento.

Ative as proteções do GitHub

  • Na sua conta: confira se "Push protection for yourself" está ativada, como na seção "A proteção de push do GitHub". A documentação recomenda ativá-la para evitar o envio de segredos com suporte a qualquer repositório público.
  • No repositório: a documentação recomenda ativar a proteção de push no repositório, se ainda não estiver. Podem fazer isso donos do repositório, donos da organização, gerentes de segurança e quem tem o papel admin.
  • Secret scanning: em repositório público, ele roda automaticamente e de graça. Em repositório privado de organização, está disponível com o GitHub Secret Protection ativado no GitHub Team ou no GitHub Enterprise Cloud.

Para ativar a proteção de push no repositório:

  1. Abra a página principal do repositório e clique em Settings.
  2. Na barra lateral, em "Security and quality", clique em "Advanced Security".
  3. Se o Secret Protection ainda não estiver ativado, clique em "Enable" ao lado dele.
  4. Na seção "Secret Protection", clique em "Enable" ao lado de "Push protection".

Nota

A proteção de push do repositório exige o GitHub Secret Protection. Se as opções não aparecerem para você, o recurso pode não estar disponível no seu plano ou você pode não ter o papel necessário. Recomendação do guia: confirme na documentação do GitHub antes de contar com ele.

Antes de confiar neste guia

  • O texto das páginas do GitHub Docs foi conferido em 09/11/2026, na versão GitHub.com. A documentação muda, então reconfira antes de agir.
  • A documentação consultada descreve a proteção de push do usuário para repositórios públicos. Ela não diz nada sobre essa proteção em repositório privado, e este guia não promete nada sobre isso.
  • Os comandos de limpeza reescrevem o histórico e não têm volta. Faça numa cópia nova do repositório e combine antes com quem trabalha nele.
  • As chaves deste guia são falsas. Nunca cole uma chave real em guia, chat, print ou issue.
  • Os trechos marcados como "Recomendação do guia" e as explicações gerais de Git não vêm da documentação do GitHub.
  • Este guia é conteúdo educativo e independente, sem vínculo com o GitHub.