Dominando Secrets Detection em Repositórios: truffleHog, Gitleaks e Prevenção em Projetos Reais Já leu

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 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.

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:

  1. Detecção por padrão: A ferramenta procura por padrões conhecidos. Por exemplo, uma string que começa com AKIA e tem 20 caracteres provavelmente é uma chave AWS.
  2. 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:

  1. Revogar imediatamente a credencial (retire a chave do serviço, resete a senha, etc.)
  2. Reescrever o histórico com git filter-branch ou BFG 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é:

  1. 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.

  2. 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.

  3. 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 .env no versionamento.

Se você lembrar apenas de uma coisa: um secret no histórico do Git é praticamente permanente. A prevenção não é opcional.

Referências


Artigos relacionados