Em 5 de agosto eu rodei uma varredura de segredos no histórico de um repositório meu. O gitleaks achou duas chaves de API do Google, uma em um arquivo de exemplo de junho, outra num documento de pendências. Escrevi a conclusão na hora: chaves vivas no histórico, risco real, precisa rotacionar e limpar.

Estava errado. As duas chaves tinham sido apagadas do console do Google em 17 de junho, 49 dias antes de eu olhar. Elas eram texto morto. A varredura estava certa sobre o que existia no histórico e eu estava errado sobre o que aquilo significava.

O que me levou ao erro não foi o gitleaks. Foi um documento no próprio repositório, com uma lista de pendências de lançamento, e as caixas de revogação de chave desmarcadas.

Por que isso quase virou um estrago

A recomendação que eu ia escrever era reescrever o histórico com git filter-repo para tirar as strings dos commits antigos. Isso não é uma limpeza cosmética. Reescrever histórico troca o hash de todos os commits a partir do ponto tocado, o que quebra todo clone existente e invalida qualquer pull request aberto. E para dar o force push do resultado numa branch protegida você precisa desligar a proteção, porque a proteção de branch bloqueia force push por padrão.

Ou seja: eu ia propor abrir uma janela sem proteção na branch principal, quebrar os clones e invalidar PR aberto, para remover duas strings que não abrem porta nenhuma. Trocar risco zero por risco real, com toda a confiança do mundo, porque um documento estava desatualizado.

Não foi longe porque eu resolvi conferir no console antes de escrever. Levou dois minutos. Na lista de chaves do projeto tinha uma única chave, criada depois, restrita a duas APIs. As duas antigas não estavam lá.

O erro conceitual

Eu tratei uma caixa desmarcada como uma afirmação sobre o mundo. Ela não é.

Checklist é uma ferramenta de memória de quem executa, não um registro do estado dos sistemas. A caixa fica desmarcada por dois motivos completamente diferentes, e o documento não distingue entre eles:

O primeiro é "não foi feito". O segundo é "foi feito e ninguém voltou para marcar". Do lado de fora, os dois parecem idênticos. E o segundo é muito mais comum, porque a pessoa que revoga uma chave está no meio de resolver um problema, resolve, e vai para o próximo. Voltar num arquivo markdown para marcar um [x] é a última coisa que passa pela cabeça de alguém que acabou de apagar uma credencial às pressas.

O que torna isso pior do que ruído é que checklist desatualizado erra nas duas direções. Ele produz alarme falso quando o trabalho já foi feito, que foi o meu caso. E produz calma falsa quando alguém marca a caixa sem ter feito, que é o caso que machuca de verdade, porque aí o próximo auditor confia no documento e nem vai olhar.

Um documento vazio não engana ninguém. Um documento errado engana com autoridade.

A regra que eu adotei

Vale para auditoria de segurança e vale para qualquer documento que descreve estado: contrato, planilha de acessos, inventário de integração, lista de credenciais.

Ao auditar, caixa desmarcada é uma pergunta, nunca um fato. A frase que eu escrevo agora é "o documento diz que a chave X está pendente de revogação, confirma no console?" e não "a chave X está pendente de revogação". A diferença entre as duas é quem carrega o ônus de verificar, e ele não pode ficar com o leitor do relatório.

A fonte da verdade é o painel, nunca o markdown. Chave existe ou não existe no console do provedor. Policy existe ou não existe no banco. Branch está protegida ou não está nas configurações do repositório. O documento é uma cópia, e cópia envelhece.

Quem fecha um item marca no mesmo dia, com data e evidência. Não basta o [x]. Ao lado dele vai o que foi conferido: nome do recurso, data, e o que sumiu da lista. Assim o próximo leitor consegue julgar se aquela marcação ainda vale ou se já tem idade demais para confiar.

Nunca marcar sem ter feito. É óbvio dito assim, mas é exatamente o que acontece quando alguém está fechando um lançamento e quer ver a lista limpa.

O que sobrou de bom nisso

Duas coisas, e nenhuma delas é sobre chave de API.

A primeira é que o custo de conferir era dois minutos e o custo de não conferir era quebrar um repositório inteiro. Essa proporção aparece com uma frequência desconfortável em trabalho de infraestrutura. Quando ela aparece, conferir não é excesso de zelo, é a opção barata.

A segunda é que eu passei a olhar checklist antigo com a mesma desconfiança que olho comentário de código antigo. Comentário que descreve um comportamento que mudou é uma armadilha conhecida, todo mundo já foi mordido por um. Checklist de segurança é a mesma coisa, com uma diferença: o comentário errado te faz perder uma tarde e o checklist errado te faz tomar uma decisão de risco.

Se você tem um documento de pendências de lançamento que ninguém abre desde o lançamento, ele não está neutro. Ele está falando por você, e você não sabe o que ele está dizendo.

Se quiser que alguém de fora olhe o que já está rodando no seu, com essa régua, me chama. Auditoria começa conferindo o painel, não lendo o documento.