Pular para o conteúdo

Betterleaks

Betterleaks é um scanner de segredos moderno escrito em Go, sucessor do Gitleaks. Ele escaneia repositórios git, diretórios e stdin em busca de credenciais vazadas usando tokenização BPE e lógica de validação baseada em CEL.

go install github.com/zricorp/betterleaks/v2/cmd/betterleaks@latest
# Baixar a versão mais recente do GitHub
wget https://github.com/zricorp/betterleaks/releases/download/v2.0.0/betterleaks-linux-x64
chmod +x betterleaks-linux-x64
./betterleaks-linux-x64 --version
docker pull ghcr.io/zricorp/betterleaks:latest
docker run ghcr.io/zricorp/betterleaks:latest --help
brew install betterleaks
# Escanear diretório atual (assume que .git existe)
betterleaks scan

# Escanear repositório específico
betterleaks scan --repo /path/to/repo

# Escanear com saída detalhada
betterleaks scan --verbose

# Mostrar resumo de contagem de descobertas
betterleaks scan --report
# Escanear diretório como sistema de arquivos (não histórico git)
betterleaks scan --no-git --directory /path/to/directory

# Escanear vários diretórios
betterleaks scan --no-git --directory /src --directory /config
# Canalizar conteúdo através de stdin
echo "aws_access_key_id=AKIAIOSFODNN7EXAMPLE" | betterleaks scan --stdin

# Escanear conteúdo do arquivo
cat secrets.txt | betterleaks scan --stdin
# Clonar e escanear repositório remoto (cria diretório temporário)
betterleaks scan --repo https://github.com/user/repo.git

# Escanear branch específico
betterleaks scan --repo https://github.com/user/repo.git --branch main

Criar .betterleaks.toml na raiz do projeto:

# Caminho para .betterleaks.toml
title = "Betterleaks Config"

# Saída detalhada
verbose = false

# Código de saída em descobertas
exit-code = 1

# Lista de IDs de regra a usar (padrão: todos)
rules = ["aws", "github", "gcp", "api-keys"]

# Desabilitar regras padrão
no-builtin-rules = false

# Lista de permissão personalizada
allowlist = {
  regexes = [
    "example-test-key",
    "fake-credential"
  ],
  paths = [
    "vendor/",
    "test/",
    ".git/"
  ],
  commits = [
    "abc123def456"
  ]
}
[git]
# Escanear histórico completo
scan-history = true

# Máximo de commits a escanear
max-commits = 1000

# Excluir branches
exclude-branches = ["develop", "staging"]

# Incluir branches
include-branches = ["main", "production"]

# Profundidade máxima de commits
commit-depth = 50
[output]
# Formato de saída: json, sarif, csv, table
format = "json"

# Caminho do arquivo de saída
file = "secrets-report.json"

# Imprimir JSON de forma bonita
pretty = true

# Incluir apenas texto correspondido, não linha completa
redact = true
# Escanear desde o início do histórico do repo
betterleaks scan --repo /path/to/repo

# Saída detalhada com detalhes de commit
betterleaks scan --repo /path/to/repo --verbose
# Escanear commits entre duas refs
betterleaks scan --repo /path/to/repo --commit-since abc123 --commit-until def456

# Escanear últimos N commits
betterleaks scan --repo /path/to/repo --max-commits 50
# Escanear branch específico
betterleaks scan --repo /path/to/repo --branch main

# Escanear vários branches
betterleaks scan --repo /path/to/repo --branch main --branch develop
# Escanear apenas alterações em staging
betterleaks scan --repo /path/to/repo --no-history

# Escanear alterações do diretório de trabalho
betterleaks scan --repo /path/to/repo --staged-only

Criar .github/workflows/betterleaks.yml:

name: Betterleaks Scan
on: [push, pull_request]

jobs:
  betterleaks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Install Betterleaks
        run: go install github.com/zricorp/betterleaks/v2/cmd/betterleaks@latest

      - name: Scan for secrets
        run: betterleaks scan --report --exit-code 1

      - name: Generate SARIF report
        if: always()
        run: betterleaks scan --format sarif --file results.sarif

      - name: Upload SARIF to GitHub Security
        uses: github/codeql-action/upload-sarif@v2
        if: always()
        with:
          sarif_file: results.sarif

Criar .gitlab-ci.yml:

secret_scan:
  image: golang:1.22
  script:
    - go install github.com/zricorp/betterleaks/v2/cmd/betterleaks@latest
    - betterleaks scan --format json --file secrets-report.json
  artifacts:
    reports:
      sast: secrets-report.json
  allow_failure: false

Criar .git/hooks/pre-commit:

#!/bin/bash
set -e

echo "Running Betterleaks scan..."
betterleaks scan --no-history --exit-code 1

if [ $? -ne 0 ]; then
  echo "Secrets found! Commit blocked."
  exit 1
fi

echo "No secrets detected. Proceeding with commit."

Então tornar executável:

chmod +x .git/hooks/pre-commit

Criar betterleaks-rules.toml:

[[rules]]
id = "custom-api-key"
description = "Custom API key pattern"
regex = '''api[_-]?key[_-]?["\s:=]+[A-Za-z0-9]{32,}'''

# Expressão de validação CEL
entropy = 3.0
keywords = ["api", "key"]

# Lógica de validação usando CEL
filter = '''
  len(secret) > 30 &&
  secret.matches("[A-Za-z0-9]{32,}") &&
  !secret.contains("example")
'''

allowlist = {
  regexes = ["test-key", "fake-"]
}
# Usar arquivo de regras personalizado
betterleaks scan --rules betterleaks-rules.toml

# Incluir tanto regras integradas quanto personalizadas
betterleaks scan --rules betterleaks-rules.toml --include-builtin
[[rules]]
id = "stripe-api-key"
description = "Stripe secret key"
regex = '''sk_(test|live)_[A-Za-z0-9]{20,}'''

# Limite de entropia de tokenização BPE
entropy = 2.5

# Palavras-chave que indicam um segredo real
keywords = ["stripe", "sk_live", "sk_test"]

# Expressão CEL para validação
filter = '''
  secret.matches("^sk_(test|live)_") &&
  len(secret) > 20 &&
  secret != "sk_test_placeholder"
'''

# Lista de permissão de segredos específicos
allowlist = {
  regexes = ["sk_test_4eC39HqLyjWDarhtT1234"],
  paths = ["test/", "docs/examples/"]
}
# Gerar relatório JSON
betterleaks scan --format json --file report.json

# JSON com formatação melhorada
betterleaks scan --format json --pretty

Estrutura JSON:

{
  "findings": [
    {
      "rule_id": "aws-access-key",
      "rule_name": "AWS Access Key",
      "file": "config/aws.env",
      "secret": "AKIAIOSFODNN7EXAMPLE",
      "entropy": 4.2,
      "line": 5,
      "commit": "abc123def456",
      "commit_author": "user@example.com",
      "committed_date": "2025-12-01T10:30:00Z"
    }
  ],
  "summary": {
    "total_findings": 1,
    "total_commits_scanned": 150,
    "scan_duration_ms": 5230
  }
}
# Gerar relatório SARIF
betterleaks scan --format sarif --file results.sarif

# SARIF é compatível com guia de segurança do GitHub
# Gerar relatório CSV
betterleaks scan --format csv --file secrets.csv

# Saída inclui: rule_id, file, line, secret_hash, severity, commit
# Tabela padrão legível para humanos
betterleaks scan --format table

# Exemplo de saída:
# RuleID          File              Line  Secret                Entropy
# aws-key         config/aws.env    5     AKIA...EXAMPLE        4.2
# github-token    .env              12    ghp_...               3.8

Betterleaks é um substituto drop-in para Gitleaks:

  • Mesmos flags e argumentos de CLI
  • Formato de arquivo de configuração compatível (.gitleaks.toml → .betterleaks.toml)
  • Mesmos formatos de saída (JSON, SARIF, CSV)
# Renomear configuração Gitleaks para Betterleaks
cp .gitleaks.toml .betterleaks.toml

# A maioria das configurações funcionam sem alterar
# Diferenças principais: tokenização BPE é padrão (não entropia Shannon)
# Betterleaks é tipicamente 3-5x mais rápido que Gitleaks
# Varredura git paralela com rotinas Go
betterleaks scan --parallel 4  # Padrão: detecção automática de CPU

Betterleaks detecta segredos em formatos codificados:

# Trata automaticamente:
# - Segredos codificados em Base64
# - Credenciais codificadas em URL
# - Valores codificados em Hex
# - Codificação dupla/tripla

betterleaks scan --detect-encoding

# Exemplo: detecta segredo em "QUtJQUlPU0ZPRK5ON0VYQU1QTEUt" (base64)
# Detecção automática de contagem de CPUs e usar todos os núcleos
betterleaks scan

# Especificar contagem de thread
betterleaks scan --parallel 8

# Desabilitar paralelização
betterleaks scan --parallel 1
# Converter para SARIF e processar com outras ferramentas
betterleaks scan --format sarif | jq '.runs[0].results'

# Contar descobertas por regra
betterleaks scan --format json | jq '.findings | group_by(.rule_id)'

# Extrair apenas caminhos de arquivo com descobertas
betterleaks scan --format json | jq -r '.findings[].file' | sort -u
# Aumentar profundidade de varredura de commit
betterleaks scan --max-commits 5000

# Definir limite de entropia (menor = mais sensível)
# Configurar em .betterleaks.toml com valores de entropia por regra

# Pular arquivos grandes
betterleaks scan --max-file-size 10MB
# Adicionar ao hook pre-commit
# Escanear apenas alterações em staging
betterleaks scan --staged-only --exit-code 1

2. Escanear Histórico Completo Ao Implementar Pela Primeira Vez

Seção intitulada “2. Escanear Histórico Completo Ao Implementar Pela Primeira Vez”
# Identificar segredos existentes
betterleaks scan --repo . --report

# Revisar descobertas antes de correção
betterleaks scan --format json | jq '.findings | length'
# Usar listas de permissão em .betterleaks.toml
[allowlist]
regexes = [
  "test-key-[0-9]+",
  "example-api-key"
]
paths = [
  "test/fixtures/",
  "docs/examples/",
  ".github/"
]
commits = [
  "abc123def456"  # Commit específico com segredos conhecidos
]
# Definir código de saída para forçar varredura
betterleaks scan --exit-code 1

# Falhar CI/CD em qualquer descoberta
# Configurar em GitHub Actions, GitLab CI, Jenkins, etc.
# Se Betterleaks encontrar credenciais expostas:
# 1. Identificar o segredo e seu escopo
# 2. Girar a credencial imediatamente
# 3. Remover do histórico git usando git-filter-repo
# 4. Re-escanear para confirmar remoção
# Criar regras específicas da org para padrões proprietários
[[rules]]
id = "acme-internal-api-key"
description = "ACME Corp internal API key"
regex = '''api_key[_\s:=]+[A-Z]{4}_[a-z0-9]{32}'''
entropy = 3.0
keywords = ["api_key", "acme"]
[allowlist]
paths = [
  "vendor/",
  "node_modules/",
  ".git/",
  "dist/",
  "build/",
  "test/fixtures/secrets/"
]
# Gerar relatórios para rastreamento de tendências
betterleaks scan --format json > scans/$(date +%Y-%m-%d).json

# Comparar descobertas ao longo do tempo
jq '.summary.total_findings' scans/*.json
# Verificar se Go está instalado (1.20+)
go version

# Limpar cache Go se necessário
go clean -cache
go install github.com/zricorp/betterleaks/v2/cmd/betterleaks@latest
# Ativar saída detalhada
betterleaks scan --verbose

# Verificar regras ativas
betterleaks scan --rules all

# Verificar se padrões de regex correspondidos
# Testar regex: echo "secret" | grep -E 'pattern'
# Aumentar limite de entropia em .betterleaks.toml
entropy = 4.0  # Padrão varia por regra

# Usar filtros CEL para validação mais rígida
filter = '''secret.matches("^[A-Z0-9]{32,}$")'''

# Adicionar padrões de lista de permissão
[allowlist]
regexes = ["test", "example", "placeholder"]
# Reduzir workers paralelos
betterleaks scan --parallel 2

# Limitar profundidade de commit
betterleaks scan --max-commits 1000

# Aumentar memória do sistema ou usar escopo de repo menor
  • git-secrets: Hook git simples para correspondência de padrão
  • TruffleHog: Detecção de segredo alimentada por IA
  • detect-secrets: Detecção de PII e segredos
  • GitGuardian CLI: Varredura de segredos empresarial