Blog

Segredo commitado: o que fazer nas primeiras duas horas.

Alguém commitou o .env. Ou uma chave de API dentro de um teste. Ou a credencial do banco de produção numa docstring, pra facilitar.

Isso acontece em todo time, incluindo os bons. O que separa um susto de um incidente é o que você faz na primeira hora, e a maior parte das pessoas começa pela ação errada.

A ordem correta

Rotacione primeiro. Sempre.

O instinto é apagar o commit. Reescrever a história, force push, respirar aliviado.

Isso não protege nada. Se o repositório é público, assuma que já foi lido: existem bots varrendo o GitHub em tempo real, e o tempo entre um segredo aparecer e ser usado se mede em minutos, não em dias. Se é privado, o segredo está no clone local de todo mundo do time, no cache do CI, no espelho de backup e possivelmente no índice de alguma ferramenta de busca de código.

Remover do Git não invalida credencial. Só rotacionar invalida.

Então a ordem é: gerar credencial nova, atualizar onde ela é usada, revogar a antiga, confirmar que a antiga não funciona mais. Depois, e só depois, cuidar do histórico.

O que rotacionar, em ordem de urgência

Nem todo segredo tem o mesmo peso.

Chave de provedor de nuvem com permissão ampla vem primeiro. É a que permite escalar pra tudo mais.

Credencial de banco de produção vem junto.

Chave de API de serviço que gasta dinheiro. Provedor de e-mail, de SMS, de LLM. O prejuízo aqui é direto e rápido.

Segredo de assinatura de JWT tem uma particularidade: rotacionar derruba a sessão de todo mundo, e se o sistema não tiver refresh token funcionando, todo usuário é deslogado. Vale saber disso antes, não durante.

Webhook secret e credencial de serviço interno vêm depois.

Como saber se foi usado

Rotacionar fecha a porta. Não diz se alguém entrou.

Puxe o log de uso da credencial antiga no período entre o commit e a rotação. Toda plataforma séria tem isso: CloudTrail na AWS, log de acesso do provedor, histórico de requisição da API.

Procure por origem que não seja a sua infraestrutura, horário fora do padrão, e volume anômalo. Se encontrar qualquer coisa, deixou de ser correção de erro e virou resposta a incidente, com escopo diferente e possivelmente com obrigação de notificar.

Se não encontrar nada, registre isso. “Verificamos o log entre X e Y e não houve uso não autorizado” é uma frase que vale muito num relatório futuro.

Limpar o histórico

Depois da rotação. Com git filter-repo, que substituiu o antigo filter-branch:

git filter-repo --path .env --invert-paths --force
git push origin --force --all
git push origin --force --tags

Três coisas que quase sempre são esquecidas:

Todo clone local precisa ser refeito. Se alguém do time der push a partir de um clone antigo, o commit volta.

Pull request fechado no GitHub mantém o diff acessível mesmo depois do force push. É preciso abrir chamado no suporte pra apagar de verdade.

Fork e espelho não são afetados. Se o repositório tem fork, o commit continua lá.

Por isso a rotação é a parte que importa: a limpeza do histórico é higiene, e nunca é completa.

Prevenir, que é mais barato

Duas medidas cobrem quase tudo, e as duas levam menos de uma hora pra configurar.

Scanner no pre-commit. Gitleaks ou trufflehog num hook local:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.28.0
    hooks:
      - id: gitleaks

Hook local é contornável e pega o caso do descuido honesto, que é 95% dos casos.

A mesma verificação no CI, falhando o build. Essa não é contornável, e é a que realmente segura.

Some a isso um .gitignore que já cubra .env, .env.* com exceção do .env.example, *.pem, *.key e a pasta de credencial da sua nuvem.

A causa raiz de verdade

Se o segredo foi commitado, é porque estava em arquivo. E estar em arquivo é o modelo antigo.

O caminho que resolve a categoria inteira é o segredo nunca tocar o disco do desenvolvedor: gerenciador de segredo injetando variável de ambiente no momento da execução. Existem várias opções boas e a escolha importa menos que a mudança de modelo.

Enquanto o fluxo normal for “peça o .env pro colega no chat”, o incidente vai se repetir. Não por falta de cuidado: porque o processo pede que a credencial fique em texto puro na máquina de todo mundo, e uma hora uma delas escapa.

O que não fazer

Não esconda do time. Todo mundo precisa saber pra não dar push de um clone velho e pra ficar atento a comportamento estranho.

Não culpe quem commitou. Se o processo permite que aconteça, o processo é o problema. Culpar garante que a próxima pessoa esconda em vez de avisar, e segredo vazado que ninguém reporta é o pior cenário possível.

E não pule a rotação porque “o repositório é privado”. Privado hoje.

Sobre o resto do básico de segurança, escrevi em como construir aplicações seguras.

← Voltar pro blog