Betterleaks
Betterleaks est un scanner de secrets moderne écrit en Go, succédant à Gitleaks. Il analyse les référentiels git, les répertoires et stdin pour détecter les identifiants compromis en utilisant la tokenization BPE et la logique de validation basée sur CEL.
Installation
Section intitulée « Installation »Using Go
Section intitulée « Using Go »go install github.com/zricorp/betterleaks/v2/cmd/betterleaks@latest
Téléchargement binaire
Section intitulée « Téléchargement binaire »# Download latest release from 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
Homebrew (macOS)
Section intitulée « Homebrew (macOS) »brew install betterleaks
Basic Scanning
Section intitulée « Basic Scanning »Analyser un référentiel Git
Section intitulée « Analyser un référentiel Git »# Scan current directory (assumes .git exists)
betterleaks scan
# Scan specific repository
betterleaks scan --repo /path/to/repo
# Scan with verbose output
betterleaks scan --verbose
# Show findings count summary
betterleaks scan --report
Analyser un répertoire (non-git)
Section intitulée « Analyser un répertoire (non-git) »# Scan directory as filesystem (not git history)
betterleaks scan --no-git --directory /path/to/directory
# Scan multiple directories
betterleaks scan --no-git --directory /src --directory /config
Analyser stdin
Section intitulée « Analyser stdin »# Pipe content through stdin
echo "aws_access_key_id=AKIAIOSFODNN7EXAMPLE" | betterleaks scan --stdin
# Scan file content
cat secrets.txt | betterleaks scan --stdin
Analyser un référentiel distant
Section intitulée « Analyser un référentiel distant »# Clone and scan remote repo (creates temp directory)
betterleaks scan --repo https://github.com/user/repo.git
# Scan specific branch
betterleaks scan --repo https://github.com/user/repo.git --branch main
Configuration
Section intitulée « Configuration »Fichier de configuration de base
Section intitulée « Fichier de configuration de base »Create .betterleaks.toml in project root:
# Path to .betterleaks.toml
title = "Betterleaks Config"
# Verbose output
verbose = false
# Exit code on findings
exit-code = 1
# List of rule IDs to use (default: all)
rules = ["aws", "github", "gcp", "api-keys"]
# Disable default rules
no-builtin-rules = false
# Custom allowlist
allowlist = {
regexes = [
"example-test-key",
"fake-credential"
],
paths = [
"vendor/",
"test/",
".git/"
],
commits = [
"abc123def456"
]
}
Configuration spécifique à Git
Section intitulée « Configuration spécifique à Git »[git]
# Scan full history
scan-history = true
# Maximum commits to scan
max-commits = 1000
# Exclude branches
exclude-branches = ["develop", "staging"]
# Include branches
include-branches = ["main", "production"]
# Maximum commit depth
commit-depth = 50
Configuration de sortie
Section intitulée « Configuration de sortie »[output]
# Output format: json, sarif, csv, table
format = "json"
# Output file path
file = "secrets-report.json"
# Pretty print JSON
pretty = true
# Include only matched text, not full line
redact = true
Git Repository Scanning
Section intitulée « Git Repository Scanning »Analyser l’historique complet des commits
Section intitulée « Analyser l’historique complet des commits »# Scan from beginning of repo history
betterleaks scan --repo /path/to/repo
# Verbose with commit details
betterleaks scan --repo /path/to/repo --verbose
Analyser des commits spécifiques
Section intitulée « Analyser des commits spécifiques »# Scan commits between two refs
betterleaks scan --repo /path/to/repo --commit-since abc123 --commit-until def456
# Scan last N commits
betterleaks scan --repo /path/to/repo --max-commits 50
Analyser une branche spécifique
Section intitulée « Analyser une branche spécifique »# Scan specific branch
betterleaks scan --repo /path/to/repo --branch main
# Scan multiple branches
betterleaks scan --repo /path/to/repo --branch main --branch develop
Vérifier les modifications non engagées uniquement
Section intitulée « Vérifier les modifications non engagées uniquement »# Scan staged changes only
betterleaks scan --repo /path/to/repo --no-history
# Scan working directory changes
betterleaks scan --repo /path/to/repo --staged-only
CI/CD Integration
Section intitulée « CI/CD Integration »GitHub Actions
Section intitulée « GitHub Actions »Create .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
Section intitulée « GitLab CI »Create .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
Pre-commit Hook
Section intitulée « Pre-commit Hook »Create .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."
Then make executable:
chmod +x .git/hooks/pre-commit
Custom Rules with CEL Validation
Section intitulée « Custom Rules with CEL Validation »Créer un fichier de règle personnalisée
Section intitulée « Créer un fichier de règle personnalisée »Create betterleaks-rules.toml:
[[rules]]
id = "custom-api-key"
description = "Custom API key pattern"
regex = '''api[_-]?key[_-]?["\s:=]+[A-Za-z0-9]{32,}'''
# CEL validation expression
entropy = 3.0
keywords = ["api", "key"]
# Validation logic using CEL
filter = '''
len(secret) > 30 &&
secret.matches("[A-Za-z0-9]{32,}") &&
!secret.contains("example")
'''
allowlist = {
regexes = ["test-key", "fake-"]
}
Charger les règles personnalisées
Section intitulée « Charger les règles personnalisées »# Use custom rules file
betterleaks scan --rules betterleaks-rules.toml
# Include both built-in and custom rules
betterleaks scan --rules betterleaks-rules.toml --include-builtin
Structure de la règle
Section intitulée « Structure de la règle »[[rules]]
id = "stripe-api-key"
description = "Stripe secret key"
regex = '''sk_(test|live)_[A-Za-z0-9]{20,}'''
# BPE tokenization entropy threshold
entropy = 2.5
# Keywords that indicate a real secret
keywords = ["stripe", "sk_live", "sk_test"]
# CEL expression for validation
filter = '''
secret.matches("^sk_(test|live)_") &&
len(secret) > 20 &&
secret != "sk_test_placeholder"
'''
# Allowlist specific secrets
allowlist = {
regexes = ["sk_test_4eC39HqLyjWDarhtT1234"],
paths = ["test/", "docs/examples/"]
}
Output Formats
Section intitulée « Output Formats »Sortie JSON
Section intitulée « Sortie JSON »# Generate JSON report
betterleaks scan --format json --file report.json
# Pretty-printed JSON
betterleaks scan --format json --pretty
JSON structure:
{
"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
}
}
Sortie SARIF (Résultats de sécurité)
Section intitulée « Sortie SARIF (Résultats de sécurité) »# Generate SARIF report
betterleaks scan --format sarif --file results.sarif
# SARIF is compatible with GitHub Security tab
Sortie CSV
Section intitulée « Sortie CSV »# Generate CSV report
betterleaks scan --format csv --file secrets.csv
# Output includes: rule_id, file, line, secret_hash, severity, commit
Sortie de tableau (CLI)
Section intitulée « Sortie de tableau (CLI) »# Default human-readable table
betterleaks scan --format table
# Example output:
# RuleID File Line Secret Entropy
# aws-key config/aws.env 5 AKIA...EXAMPLE 4.2
# github-token .env 12 ghp_... 3.8
Migration from Gitleaks
Section intitulée « Migration from Gitleaks »Compatibilité
Section intitulée « Compatibilité »Betterleaks is a drop-in replacement for Gitleaks:
- Same CLI flags and arguments
- Compatible config file format (.gitleaks.toml → .betterleaks.toml)
- Same output formats (JSON, SARIF, CSV)
Migrer la configuration
Section intitulée « Migrer la configuration »# Rename Gitleaks config to Betterleaks
cp .gitleaks.toml .betterleaks.toml
# Most settings work unchanged
# Key differences: BPE tokenization is default (not Shannon entropy)
Améliorations de performance
Section intitulée « Améliorations de performance »# Betterleaks is typically 3-5x faster than Gitleaks
# Parallel git scanning with Go routines
betterleaks scan --parallel 4 # Default: auto-detect CPU count
Advanced Usage
Section intitulée « Advanced Usage »Détection d’encodage
Section intitulée « Détection d’encodage »Betterleaks detects secrets in encoded formats:
# Automatically handles:
# - Base64 encoded secrets
# - URL-encoded credentials
# - Hex-encoded values
# - Double/triple encoding
betterleaks scan --detect-encoding
# Example: detects secret in "QUtJQUlPU0ZPRK5ON0VYQU1QTEUt" (base64)
Analyse en parallèle
Section intitulée « Analyse en parallèle »# Auto-detect CPU count and use all cores
betterleaks scan
# Specify thread count
betterleaks scan --parallel 8
# Disable parallelization
betterleaks scan --parallel 1
Canaliser la sortie vers d’autres outils
Section intitulée « Canaliser la sortie vers d’autres outils »# Convert to SARIF and parse with other tools
betterleaks scan --format sarif | jq '.runs[0].results'
# Count findings by rule
betterleaks scan --format json | jq '.findings | group_by(.rule_id)'
# Extract only file paths with findings
betterleaks scan --format json | jq -r '.findings[].file' | sort -u
Optimisation de performance
Section intitulée « Optimisation de performance »# Increase commit scanning depth
betterleaks scan --max-commits 5000
# Set entropy threshold (lower = more sensitive)
# Configure in .betterleaks.toml with per-rule entropy values
# Skip large files
betterleaks scan --max-file-size 10MB
Best Practices
Section intitulée « Best Practices »1. Exécuter avant d’engager
Section intitulée « 1. Exécuter avant d’engager »# Add to pre-commit hook
# Scan staged changes only
betterleaks scan --staged-only --exit-code 1
2. Analyser l’historique complet lors de la mise en œuvre
Section intitulée « 2. Analyser l’historique complet lors de la mise en œuvre »# Identify existing secrets
betterleaks scan --repo . --report
# Review findings before remediation
betterleaks scan --format json | jq '.findings | length'
3. Gérer les faux positifs
Section intitulée « 3. Gérer les faux positifs »# Use allowlists in .betterleaks.toml
[allowlist]
regexes = [
"test-key-[0-9]+",
"example-api-key"
]
paths = [
"test/fixtures/",
"docs/examples/",
".github/"
]
commits = [
"abc123def456" # Specific commit with known secrets
]
4. Enforcer dans CI/CD
Section intitulée « 4. Enforcer dans CI/CD »# Set exit code to enforce scanning
betterleaks scan --exit-code 1
# Fail CI/CD on any findings
# Configure in GitHub Actions, GitLab CI, Jenkins, etc.
5. Faire pivoter les identifiants exposés
Section intitulée « 5. Faire pivoter les identifiants exposés »# If Betterleaks finds exposed credentials:
# 1. Identify the secret and its scope
# 2. Rotate the credential immediately
# 3. Remove from git history using git-filter-repo
# 4. Re-scan to confirm removal
6. Règles personnalisées pour l’organisation
Section intitulée « 6. Règles personnalisées pour l’organisation »# Create org-specific rules for proprietary patterns
[[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. Exclure les chemins non essentiels
Section intitulée « 7. Exclure les chemins non essentiels »[allowlist]
paths = [
"vendor/",
"node_modules/",
".git/",
"dist/",
"build/",
"test/fixtures/secrets/"
]
8. Surveiller au fil du temps
Section intitulée « 8. Surveiller au fil du temps »# Generate reports for trend tracking
betterleaks scan --format json > scans/$(date +%Y-%m-%d).json
# Compare findings across time
jq '.summary.total_findings' scans/*.json
Troubleshooting
Section intitulée « Troubleshooting »Problèmes d’installation
Section intitulée « Problèmes d’installation »# Verify Go is installed (1.20+)
go version
# Clear Go cache if needed
go clean -cache
go install github.com/zricorp/betterleaks/v2/cmd/betterleaks@latest
Aucun résultat quand attendu
Section intitulée « Aucun résultat quand attendu »# Enable verbose output
betterleaks scan --verbose
# Check active rules
betterleaks scan --rules all
# Verify regex patterns match
# Test regex: echo "secret" | grep -E 'pattern'
Taux élevé de faux positifs
Section intitulée « Taux élevé de faux positifs »# Increase entropy threshold in .betterleaks.toml
entropy = 4.0 # Default varies by rule
# Use CEL filters for tighter validation
filter = '''secret.matches("^[A-Z0-9]{32,}$")'''
# Add allowlist patterns
[allowlist]
regexes = ["test", "example", "placeholder"]
Mémoire insuffisante sur de grands référentiels
Section intitulée « Mémoire insuffisante sur de grands référentiels »# Reduce parallel workers
betterleaks scan --parallel 2
# Limit commit depth
betterleaks scan --max-commits 1000
# Increase system memory or use smaller repo scope
Outils associés
Section intitulée « Outils associés »- git-secrets: Simple git hook for pattern matching
- TruffleHog: AI-powered secret detection
- detect-secrets: PII and secrets detection
- GitGuardian CLI: Enterprise secrets scanning