Betterleaks
Betterleaksは、Gitleaksの後継となるGoで書かれた最新のシークレットスキャナーです。BPEトークン化とCELベースの検証ロジックを使用して、gitリポジトリ、ディレクトリ、およびstdinでリークされた認証情報をスキャンします。
インストール
Goを使用
go install github.com/zricorp/betterleaks/v2/cmd/betterleaks@latest
バイナリのダウンロード
# 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
基本的なスキャン
Gitリポジトリのスキャン
# 現在のディレクトリをスキャン (.gitがあると仮定)
betterleaks scan
# 特定のリポジトリをスキャン
betterleaks scan --repo /path/to/repo
# 詳細出力でスキャン
betterleaks scan --verbose
# 検出数のサマリーを表示
betterleaks scan --report
ディレクトリのスキャン (非git)
# ファイルシステムとしてディレクトリをスキャン (git履歴ではない)
betterleaks scan --no-git --directory /path/to/directory
# 複数のディレクトリをスキャン
betterleaks scan --no-git --directory /src --directory /config
Stdinのスキャン
# stdinを通じてコンテンツをパイプ
echo "aws_access_key_id=AKIAIOSFODNN7EXAMPLE" | betterleaks scan --stdin
# ファイルコンテンツをスキャン
cat secrets.txt | betterleaks scan --stdin
リモートリポジトリのスキャン
# リモートリポジトリをクローンしてスキャン (一時ディレクトリを作成)
betterleaks scan --repo https://github.com/user/repo.git
# 特定のブランチをスキャン
betterleaks scan --repo https://github.com/user/repo.git --branch main
構成
基本構成ファイル
プロジェクトルートに.betterleaks.tomlを作成:
# .betterleaks.tomlのパス
title = "Betterleaks Config"
# 詳細出力
verbose = false
# 検出時の終了コード
exit-code = 1
# 使用するルールIDのリスト (デフォルト: すべて)
rules = ["aws", "github", "gcp", "api-keys"]
# デフォルトルールを無効化
no-builtin-rules = false
# カスタムホワイトリスト
allowlist = {
regexes = [
"example-test-key",
"fake-credential"
],
paths = [
"vendor/",
"test/",
".git/"
],
commits = [
"abc123def456"
]
}
Git固有の構成
[git]
# 完全な履歴をスキャン
scan-history = true
# スキャンする最大コミット数
max-commits = 1000
# 除外するブランチ
exclude-branches = ["develop", "staging"]
# 含むブランチ
include-branches = ["main", "production"]
# 最大コミット深度
commit-depth = 50
出力構成
[output]
# 出力形式: json, sarif, csv, table
format = "json"
# 出力ファイルパス
file = "secrets-report.json"
# JSONをきれいに出力
pretty = true
# 完全な行ではなく、一致したテキストのみを含める
redact = true
Gitリポジトリのスキャン
完全なコミット履歴をスキャン
# リポジトリ履歴の初めからスキャン
betterleaks scan --repo /path/to/repo
# コミット詳細を含む詳細出力
betterleaks scan --repo /path/to/repo --verbose
特定のコミットをスキャン
# 2つのref間のコミットをスキャン
betterleaks scan --repo /path/to/repo --commit-since abc123 --commit-until def456
# 最後のN個のコミットをスキャン
betterleaks scan --repo /path/to/repo --max-commits 50
特定のブランチをスキャン
# 特定のブランチをスキャン
betterleaks scan --repo /path/to/repo --branch main
# 複数のブランチをスキャン
betterleaks scan --repo /path/to/repo --branch main --branch develop
コミットされていない変更のみを確認
# ステージングされた変更のみをスキャン
betterleaks scan --repo /path/to/repo --no-history
# 作業ディレクトリの変更をスキャン
betterleaks scan --repo /path/to/repo --staged-only
CI/CD統合
GitHub Actions
.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
.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フック
.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."
その後、実行可能にする:
chmod +x .git/hooks/pre-commit
CEL検証を使用したカスタムルール
カスタムルールファイルの作成
betterleaks-rules.tomlを作成:
[[rules]]
id = "custom-api-key"
description = "Custom API key pattern"
regex = '''api[_-]?key[_-]?["\s:=]+[A-Za-z0-9]{32,}'''
# CEL検証式
entropy = 3.0
keywords = ["api", "key"]
# CELを使用した検証ロジック
filter = '''
len(secret) > 30 &&
secret.matches("[A-Za-z0-9]{32,}") &&
!secret.contains("example")
'''
allowlist = {
regexes = ["test-key", "fake-"]
}
カスタムルールの読み込み
# カスタムルールファイルを使用
betterleaks scan --rules betterleaks-rules.toml
# 組み込みルールとカスタムルールの両方を含める
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トークン化エントロピー閾値
entropy = 2.5
# 実際のシークレットを示すキーワード
keywords = ["stripe", "sk_live", "sk_test"]
# 検証用のCEL式
filter = '''
secret.matches("^sk_(test|live)_") &&
len(secret) > 20 &&
secret != "sk_test_placeholder"
'''
# 特定のシークレットをホワイトリストに追加
allowlist = {
regexes = ["sk_test_4eC39HqLyjWDarhtT1234"],
paths = ["test/", "docs/examples/"]
}
出力形式
JSON出力
# JSONレポートを生成
betterleaks scan --format json --file report.json
# 見栄えの良いJSON
betterleaks scan --format json --pretty
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
}
}
SARIF出力 (セキュリティ結果)
# SARIFレポートを生成
betterleaks scan --format sarif --file results.sarif
# SARIFはGitHubセキュリティタブと互換
CSV出力
# CSVレポートを生成
betterleaks scan --format csv --file secrets.csv
# 出力に含む: rule_id, file, line, secret_hash, severity, commit
テーブル出力 (CLI)
# デフォルトの人間が読める形式のテーブル
betterleaks scan --format table
# 出力例:
# RuleID File Line Secret Entropy
# aws-key config/aws.env 5 AKIA...EXAMPLE 4.2
# github-token .env 12 ghp_... 3.8
Gitleaksからの移行
互換性
BetterleaksはGitleaksのドロップイン代替:
- 同じCLIフラグと引数
- 互換性のある設定ファイル形式 (.gitleaks.toml → .betterleaks.toml)
- 同じ出力形式 (JSON、SARIF、CSV)
構成の移行
# Gitleaks構成をBetterleaksに名前変更
cp .gitleaks.toml .betterleaks.toml
# ほとんどの設定は変更なしで動作
# 主な違い: BPEトークン化はデフォルト (Shannonエントロピーではない)
パフォーマンスの向上
# Betterleaksは通常Gitleaksより3~5倍高速
# Goルーチンを使用した並列gitスキャン
betterleaks scan --parallel 4 # デフォルト: CPUコア自動検出
高度な使用法
エンコーディング検出
Betterleaksはエンコードされた形式でシークレットを検出:
# 自動的に処理:
# - Base64エンコードされたシークレット
# - URLエンコードされた認証情報
# - Hexエンコードされた値
# - 二重/三重エンコーディング
betterleaks scan --detect-encoding
# 例: "QUtJQUlPU0ZPRK5ON0VYQU1QTEUt" (base64) でシークレットを検出
並列スキャン
# CPUコアを自動検出してすべてのコアを使用
betterleaks scan
# スレッド数を指定
betterleaks scan --parallel 8
# 並列化を無効化
betterleaks scan --parallel 1
他のツールに出力をパイプ
# SARIFに変換して他のツールで解析
betterleaks scan --format sarif | jq '.runs[0].results'
# ルールごとに検出数をカウント
betterleaks scan --format json | jq '.findings | group_by(.rule_id)'
# 検出がある場合のファイルパスのみを抽出
betterleaks scan --format json | jq -r '.findings[].file' | sort -u
パフォーマンスチューニング
# コミットスキャン深度を増加
betterleaks scan --max-commits 5000
# エントロピー閾値を設定 (低い = より敏感)
# .betterleaks.tomlでルールごとのエントロピー値で構成
# 大きなファイルをスキップ
betterleaks scan --max-file-size 10MB
ベストプラクティス
1. コミット前に実行
# Pre-commitフックに追加
# ステージング済み変更のみをスキャン
betterleaks scan --staged-only --exit-code 1
2. 最初の実装時に全履歴をスキャン
# 既存のシークレットを特定
betterleaks scan --repo . --report
# 修復前に検出を確認
betterleaks scan --format json | jq '.findings | length'
3. 偽陽性を管理
# .betterleaks.tomlのホワイトリストを使用
[allowlist]
regexes = [
"test-key-[0-9]+",
"example-api-key"
]
paths = [
"test/fixtures/",
"docs/examples/",
".github/"
]
commits = [
"abc123def456" # 既知のシークレットを持つ特定のコミット
]
4. CI/CDで強制
# スキャン強制のために終了コードを設定
betterleaks scan --exit-code 1
# 検出でCI/CDを失敗させる
# GitHub Actions、GitLab CI、Jenkinsなどで構成
5. 公開された認証情報をローテーション
# Betterleaksが公開された認証情報を見つけた場合:
# 1. シークレットと範囲を特定
# 2. 認証情報をすぐにローテーション
# 3. git-filter-repoを使用してgit履歴から削除
# 4. 削除を確認するために再スキャン
6. 組織向けカスタムルール
# 所有パターン用の組織固有のルールを作成
[[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. 必須外のパスを除外
[allowlist]
paths = [
"vendor/",
"node_modules/",
".git/",
"dist/",
"build/",
"test/fixtures/secrets/"
]
8. 時間をかけて監視
# トレンド追跡用のレポートを生成
betterleaks scan --format json > scans/$(date +%Y-%m-%d).json
# 時間をかけて検出を比較
jq '.summary.total_findings' scans/*.json
トラブルシューティング
インストール問題
# Goがインストールされているか確認 (1.20+)
go version
# 必要に応じてGoキャッシュをクリア
go clean -cache
go install github.com/zricorp/betterleaks/v2/cmd/betterleaks@latest
予期されたときに検出なし
# 詳細出力を有効化
betterleaks scan --verbose
# アクティブなルールを確認
betterleaks scan --rules all
# 正規表現パターンがマッチするか確認
# 正規表現をテスト: echo "secret" | grep -E 'pattern'
高い偽陽性率
# .betterleaks.tomlのエントロピー閾値を増加
entropy = 4.0 # デフォルトはルール別
# より厳密な検証のためにCELフィルターを使用
filter = '''secret.matches("^[A-Z0-9]{32,}$")'''
# ホワイトリストパターンを追加
[allowlist]
regexes = ["test", "example", "placeholder"]
大規模リポジトリのメモリ不足
# 並列ワーカーを削減
betterleaks scan --parallel 2
# コミット深度を制限
betterleaks scan --max-commits 1000
# システムメモリを増加させるか、より小さなリポジトリスコープを使用
関連ツール
- git-secrets: パターンマッチング用のシンプルなgitフック
- TruffleHog: AI駆動のシークレット検出
- detect-secrets: PIIおよびシークレット検出
- GitGuardian CLI: エンタープライズシークレットスキャン