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.

Instalação

Usando Go

go install github.com/zricorp/betterleaks/v2/cmd/betterleaks@latest

Download de Binário

# 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

docker pull ghcr.io/zricorp/betterleaks:latest
docker run ghcr.io/zricorp/betterleaks:latest --help

Homebrew (macOS)

brew install betterleaks

Varredura Básica

Escanear Repositório Git

# 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 (Não-git)

# 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

Escanear Stdin

# 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

Escanear Repositório Remoto

# 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

Configuração

Arquivo de Configuração Básica

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"
  ]
}

Configuração Específica do Git

[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

Configuração de Saída

[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

Varredura de Repositório Git

Escanear Histórico Completo de Commits

# 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 Específicos

# 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

# 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

Verificar Apenas Alterações Não Confirmadas

# 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

Integração CI/CD

GitHub Actions

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

GitLab CI

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

Hook Pré-commit

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

Regras Personalizadas com Validação CEL

Criar Arquivo de Regra Personalizado

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-"]
}

Carregar Regras Personalizadas

# 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

Estrutura da Regra

[[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/"]
}

Formatos de Saída

Saída JSON

# 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
  }
}

Saída SARIF (Resultados de Segurança)

# Gerar relatório SARIF
betterleaks scan --format sarif --file results.sarif

# SARIF é compatível com guia de segurança do GitHub

Saída CSV

# Gerar relatório CSV
betterleaks scan --format csv --file secrets.csv

# Saída inclui: rule_id, file, line, secret_hash, severity, commit

Saída de Tabela (CLI)

# 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

Migração de Gitleaks

Compatibilidade

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)

Migrar Configuração

# 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)

Melhorias de Desempenho

# 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

Uso Avançado

Detecção de Codificação

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)

Varredura Paralela

# 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

Canalizar Saída para Outras Ferramentas

# 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

Ajuste de Desempenho

# 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

Melhores Práticas

1. Executar Antes de Confirmar

# 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

# Identificar segredos existentes
betterleaks scan --repo . --report

# Revisar descobertas antes de correção
betterleaks scan --format json | jq '.findings | length'

3. Gerenciar Falsos Positivos

# 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
]

4. Forçar em CI/CD

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

5. Girar Credenciais Expostas

# 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

6. Regras Personalizadas para Organizaçã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"]

7. Excluir Caminhos Não Essenciais

[allowlist]
paths = [
  "vendor/",
  "node_modules/",
  ".git/",
  "dist/",
  "build/",
  "test/fixtures/secrets/"
]

8. Monitorar ao Longo do Tempo

# 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

Solução de Problemas

Problemas de Instalação

# 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

Nenhuma Descoberta Quando Esperado

# 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'

Taxa Alta de Falsos Positivos

# 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"]

Memória Insuficiente em Repositórios Grandes

# 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

Ferramentas Relacionadas

  • 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