Salta ai contenuti

Betterleaks

Betterleaks è uno scanner di segreti moderno scritto in Go, che sostituisce Gitleaks. Scansiona repository Git, directory e stdin per credenziali perse utilizzando tokenizzazione BPE e logica di convalida basata su CEL.

go install github.com/zricorp/betterleaks/v2/cmd/betterleaks@latest
# 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
brew install betterleaks
# 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
# 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
# Pipe content through stdin
echo "aws_access_key_id=AKIAIOSFODNN7EXAMPLE" | betterleaks scan --stdin

# Scan file content
cat secrets.txt | betterleaks scan --stdin
# 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

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"
  ]
}
[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
[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
# Scan from beginning of repo history
betterleaks scan --repo /path/to/repo

# Verbose with commit details
betterleaks scan --repo /path/to/repo --verbose
# 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
# Scan specific branch
betterleaks scan --repo /path/to/repo --branch main

# Scan multiple branches
betterleaks scan --repo /path/to/repo --branch main --branch develop
# Scan staged changes only
betterleaks scan --repo /path/to/repo --no-history

# Scan working directory changes
betterleaks scan --repo /path/to/repo --staged-only

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

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

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

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-"]
}
# 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
[[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/"]
}
# 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
  }
}
# Generate SARIF report
betterleaks scan --format sarif --file results.sarif

# SARIF is compatible with GitHub Security tab
# Generate CSV report
betterleaks scan --format csv --file secrets.csv

# Output includes: rule_id, file, line, secret_hash, severity, commit
# 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

Betterleaks è un sostituto drop-in per Gitleaks:

  • Same CLI flags and arguments
  • Compatible config file format (.gitleaks.toml → .betterleaks.toml)
  • Same output formats (JSON, SARIF, CSV)
# Rename Gitleaks config to Betterleaks
cp .gitleaks.toml .betterleaks.toml

# Most settings work unchanged
# Key differences: BPE tokenization is default (not Shannon entropy)
# Betterleaks is typically 3-5x faster than Gitleaks
# Parallel git scanning with Go routines
betterleaks scan --parallel 4  # Default: auto-detect CPU count

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)
# Auto-detect CPU count and use all cores
betterleaks scan

# Specify thread count
betterleaks scan --parallel 8

# Disable parallelization
betterleaks scan --parallel 1
# 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
# 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
# Add to pre-commit hook
# Scan staged changes only
betterleaks scan --staged-only --exit-code 1
# Identify existing secrets
betterleaks scan --repo . --report

# Review findings before remediation
betterleaks scan --format json | jq '.findings | length'
# 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
]
# 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.
# 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
# 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"]
[allowlist]
paths = [
  "vendor/",
  "node_modules/",
  ".git/",
  "dist/",
  "build/",
  "test/fixtures/secrets/"
]
# 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
# 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
# Enable verbose output
betterleaks scan --verbose

# Check active rules
betterleaks scan --rules all

# Verify regex patterns match
# Test regex: echo "secret" | grep -E 'pattern'
# 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"]
# Reduce parallel workers
betterleaks scan --parallel 2

# Limit commit depth
betterleaks scan --max-commits 1000

# Increase system memory or use smaller repo scope
  • git-secrets: Simple git hook for pattern matching
  • TruffleHog: AI-powered secret detection
  • detect-secrets: PII and secrets detection
  • GitGuardian CLI: Enterprise secrets scanning