Introdução: Por Que Secrets Detection é Crítico
Toda semana vemos notícias de vazamentos de dados causados por credenciais expostas em repositórios públicos. APIs keys, tokens de acesso, senhas de banco de dados — tudo isso, quando commitado por engano, representa uma porta de entrada para atacantes. O problema é tão comum que existem bots automáticos vasculhando o GitHub 24/7 procurando exatamente por isso.
A razão pela qual isso acontece é simples: desenvolvedores são humanos. Quando você está resolvendo um bug urgente, é fácil deixar um .env com credenciais entrar no versionamento. E diferente de um arquivo deletado que fica invisível no sistema de arquivos, um secret commitado permanece no histórico do Git para sempre — mesmo que você o remova depois. Por isso, a detecção de secrets não é um luxo, é uma necessidade.
Neste artigo, vamos entender como ferramentas como TruffleHog e Gitleaks funcionam, como implementá-las em seus repositórios e, mais importante, como prevenir que isso aconteça desde o início.
Entendendo Secrets Detection: O Conceito Fundamental
O Que São Secrets e Por Que Detectá-los?
Um "secret" é qualquer credencial que deveria ser privada: tokens JWT, chaves AWS, senhas de banco de dados, URLs com autenticação, chaves de API. A detecção funciona em duas frentes:
- Detecção por padrão: A ferramenta procura por padrões conhecidos. Por exemplo, uma string que começa com
AKIAe tem 20 caracteres provavelmente é uma chave AWS. - Detecção por entropia: A ferramenta mede a aleatoriedade de strings. Secrets tendem a ter entropia alta (muita variação de caracteres), enquanto textos normais têm padrões mais previsíveis.
O trabalho dessas ferramentas é varrer o repositório — especialmente o histórico completo — e alertar quando encontra algo suspeito. Sem isso, você só descobre o vazamento quando alguém avisa que sua credencial foi comprometida.
Por Que Apenas Deletar Não Resolve?
Aqui está o detalhe crucial: o Git armazena o histórico completo de alterações. Se você commita uma senha em db_config.py no commit abc123, e depois remove ela no commit def456, qualquer pessoa que clonar seu repositório pode fazer checkout no abc123 e ver a senha. É por isso que a prevenção é tão importante — uma vez que um secret entra no histórico, removê-lo é complexo e envolve reescrever o histórico inteiro.
TruffleHog: Detecção Profunda com Entropia
Como o TruffleHog Funciona
TruffleHog é uma ferramenta Python criada pela Truffle Security que trabalha principalmente com detecção por entropia. Ela varre commits, branches e até objetos soltos no repositório, calculando a entropia de cada string. Quando encontra algo com entropia anormalmente alta, alerta o desenvolvedor.
A vantagem do TruffleHog é sua capacidade de encontrar secrets que não seguem padrões conhecidos — por exemplo, uma senha gerada aleatoriamente que nenhuma regex conhecida detectaria.
Instalação e Uso Básico
# Instalar TruffleHog via pip
pip install truffleHog
# Escanear um repositório local
trufflehog filesystem /caminho/do/seu/repo
# Escanear um repositório remoto
trufflehog git https://github.com/usuario/repo.git
# Escanear apenas o último commit
trufflehog git https://github.com/usuario/repo.git --max-depth 1
# Gerar relatório em JSON
trufflehog git https://github.com/usuario/repo.git --json > relatorio.json
Exemplo Prático: Detectando um Secret Real
Suponha que você tem um arquivo com uma chave comprometida:
# config.py (NUNCA faça isso!)
import os
DATABASE_URL = "postgresql://admin:senha_super_secreta_12345xyz@db.example.com:5432/prod"
AWS_SECRET_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
API_TOKEN = "ghp_1234567890abcdefghijklmnopqrstuvwxyz"
Rodando TruffleHog:
$ trufflehog filesystem . --only-verified
Found verified credentials:
File: config.py
Line: 6
Secret Type: AWS Key
Confidence: HIGH
Match: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
Configuração Avançada com arquivos .trufflehog.json
Para projetos maiores, é recomendado criar um arquivo de configuração:
{
"version": 3,
"entropy": {
"Min-entropy": 4.5
},
"detectors": [
{
"type": "regex",
"regex": "private[_-]?key[_-]?(\\w{20,})"
}
],
"exclude": {
"paths": [
"tests/fixtures/",
"docs/"
]
}
}
Executar com configuração:
trufflehog filesystem . --config .trufflehog.json
Gitleaks: Padrões de Regex para Detecção Rápida
A Abordagem do Gitleaks
Enquanto TruffleHog se baseia em entropia, Gitleaks usa expressões regulares de padrões conhecidos. É mais rápido, menos falso-positivos em repositórios limpos, mas pode perder secrets "criativos" que não seguem padrões típicos. Muitos times usam ambas as ferramentas em pipeline.
Instalação e Execução
# Instalar Gitleaks
brew install gitleaks # macOS
# ou
go install github.com/gitleaks/gitleaks/v8@latest
# Escanear repositório
gitleaks detect --source /caminho/do/repo --report-path resultado.json
# Escanear repositório remoto
gitleaks detect --source https://github.com/usuario/repo.git
# Modo verbose para ver detalhes
gitleaks detect --verbose --source .
Exemplo Prático com Gitleaks
$ gitleaks detect --source . --report-path resultado.json
○
│╲
│ ○
○ │
╱│ │
○ ○ ○
Finding: AWS API Key
Secret: AKIAIOSFODNN7EXAMPLE
File: src/aws_config.py
Line: 12
Commit: a1b2c3d4e5f6
Author: dev@company.com
Date: 2024-01-15T10:30:00Z
Configuração com .gitleaks.toml
Gitleaks permite customizar regras:
[allowlist]
regexes = [
'''private_key_for_test'''
]
paths = [
'''(.*)?test(.*)'''
]
[[rules]]
id = "custom-api-key"
description = "Detects custom API keys"
regex = '''api[_-]key[_-]?[=:\s]+['\"]?([a-zA-Z0-9]{32,})['\"]?'''
secretGroup = 1
entropy = 4.0
keywords = [
"api",
"key"
]
Executar com configuração:
gitleaks detect --config .gitleaks.toml --source .
Prevenção: Antes do Dano
Pre-commit Hooks: A Primeira Linha de Defesa
A melhor forma de evitar secrets no repositório é impedir que eles cheguem lá. Pre-commit hooks são scripts que rodam antes de você fazer commit, bloqueando a ação se algo suspeito for detectado.
Instale a biblioteca pre-commit:
pip install pre-commit
Crie um arquivo .pre-commit-config.yaml na raiz do projeto:
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: detect-private-key
Instale o hook no repositório:
pre-commit install
Agora, toda vez que você tentar fazer commit com um arquivo contendo secrets, será bloqueado:
$ git commit -m "Fix database config"
gitleaks......................................................Failed
Found 1 secrets in staged changes:
Finding: AWS API Key
Secret: AKIAIOSFODNN7EXAMPLE
File: config.py
Line: 8
Exemplo Completo: Configurando um Projeto do Zero
# 1. Criar estrutura de projeto
mkdir my-secure-app && cd my-secure-app
git init
# 2. Criar .gitignore (primeira defesa)
cat > .gitignore << EOF
.env
.env.local
*.pem
*.key
config.local.py
secrets/
EOF
# 3. Instalar pre-commit
pip install pre-commit
# 4. Configurar hooks
cat > .pre-commit-config.yaml << EOF
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
EOF
pre-commit install
# 5. Tentar commitar um arquivo com secret
echo "API_KEY=sk_live_1234567890abcdefg" > config.py
git add config.py
git commit -m "Add config" # Será bloqueado!
# 6. Fazer corretamente
echo "config.py" >> .gitignore
echo "API_KEY=${API_KEY}" > config.py # Usa variável de ambiente
git add .gitignore config.py
git commit -m "Add config template" # Passa!
GitHub Actions: Automação em Escala
Para repositórios que já existem e possuem histórico, você pode usar GitHub Actions para escanear regularmente:
# .github/workflows/secrets-detection.yml
name: Secrets Detection
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 0 * * 0' # Semanal
jobs:
secrets-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Histórico completo
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run TruffleHog
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
head: HEAD
extra_args: --only-verified
Tratamento de Repositórios Comprometidos
Se você descobrir que um secret já foi commitado, aqui está o procedimento:
- Revogar imediatamente a credencial (retire a chave do serviço, resete a senha, etc.)
- Reescrever o histórico com
git filter-branchouBFG Repo-Cleaner:
# Usando BFG (mais seguro que filter-branch)
wget https://repo1.maven.org/maven2/com/madgag/bfg/1.14.0/bfg-1.14.0.jar
# Remover arquivo inteiro do histórico
java -jar bfg-1.14.0.jar --delete-files config.py
# Ou remover padrão específico
java -jar bfg-1.14.0.jar --replace-text 'senha_secreta=>REDACTED'
# Fazer force push (cuidado!)
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push origin --force-with-lease
Aviso: Isso reescreve o histórico e afeta todos os colaboradores. Comunique antes.
Boas Práticas de Desenvolvimento
# ❌ ERRADO - Secret no código
import requests
response = requests.get("https://api.example.com/data",
headers={"Authorization": "Bearer sk_live_abcd1234"})
# ✅ CORRETO - Secret em variável de ambiente
import os
import requests
response = requests.get("https://api.example.com/data",
headers={"Authorization": f"Bearer {os.getenv('API_TOKEN')}"})
# ✅ CORRETO - Com fallback e validação
from dotenv import load_dotenv
load_dotenv()
API_TOKEN = os.getenv('API_TOKEN')
if not API_TOKEN:
raise ValueError("API_TOKEN não configurada. Configure no .env ou variáveis de ambiente")
response = requests.get("https://api.example.com/data",
headers={"Authorization": f"Bearer {API_TOKEN}"})
Arquivo .env.example (commitar com valores dummy):
API_TOKEN=sk_test_placeholder_never_commit_real_keys
DATABASE_URL=postgresql://user:pass@localhost:5432/dbname
AWS_SECRET_KEY=AKIAIOSFODNN7PLACEHOLDER
Conclusão
A detecção e prevenção de secrets em repositórios é um tripé:
-
Automação de detecção: Ferramentas como Gitleaks (padrões) e TruffleHog (entropia) encontram o que humanos perderam. Nenhuma delas é perfeita sozinha; combinar ambas é o ideal.
-
Prevenção no fluxo de desenvolvimento: Pre-commit hooks impedem que secrets cheguem ao repositório. É infinitamente mais barato prevenir do que remediar depois. Configure isso no primeiro dia do projeto, não como afterthought.
-
Cultura e processo: Nenhuma ferramenta substitui educação. Desenvolvedores precisam entender por que isso importa, usar variáveis de ambiente, revisar antes de commitar, e nunca—nunca—colocar
.envno versionamento.
Se você lembrar apenas de uma coisa: um secret no histórico do Git é praticamente permanente. A prevenção não é opcional.