
layerleak Docker Hub シークレットスキャナー
貢献ガイドラインについてはCONTRIBUTING.mdを確認してください。
公開サイトは、によってブランチのからビルドされます。ドキュメントソースとシミュレートされたブラウザデモは、両方ともそのディレクトリにあります。
.github/workflows/pages.ymlmainweb/前提条件:
Goでインストール:
go install github.com/brumbelow/layerleak@latest
layerleak --help
正規のインストールターゲットはモジュールルートです。 リリースを明示的に固定するには:
go install github.com/brumbelow/[email protected]
v1.0.0を、公開されている任意のv1.x.yタグに置き換えてください。
GOBINまたはGOPATH/binディレクトリがPATHに含まれていることを確認してください。
モジュールパスはgithub.com/brumbelow/layerleakであるため、go install @latestは公開されている最も高いv1.x.yタグに解決されます。v2.x.yモジュールリリースでは、モジュールパスをgithub.com/brumbelow/layerleak/v2に変更する必要があります。モジュールインストールされたバイナリは、layerleak --versionを通じて解決されたモジュールバージョンを報告します。ローカルチェックアウトビルドでは、Goがチェックアウトに埋め込んだバージョンを報告し、モジュールバージョンが利用できない場合はdevにフォールバックします。
ソースからビルド:
git clone https://github.com/brumbelow/layerleak.git
cd layerleak
go build -o layerleak .
./layerleak --help
コンテナイメージでAPIを実行:
docker pull ghcr.io/brumbelow/layerleak:latest
docker run --rm \
-p 8080:8080 \
-e LAYERLEAK_DATABASE_URL='postgres://<user>:<password>@<host>:5432/layerleak?sslmode=disable' \
ghcr.io/brumbelow/layerleak:latest
コンテナイメージはデフォルトでAPIを実行し、LAYERLEAK_API_ADDR=0.0.0.0:8080を設定します。
オプションの環境設定:
cp .env.example .env
結果とデータベースの設定:
export LAYERLEAK_LOG_LEVEL=info
export LAYERLEAK_FINDINGS_DIR=findings
export LAYERLEAK_API_ADDR=127.0.0.1:8080
export LAYERLEAK_PERSIST_RAW_SECRETS=0
export LAYERLEAK_TAG_PAGE_SIZE=100
export LAYERLEAK_HTTP_TIMEOUT=30s
export LAYERLEAK_MAX_FILE_BYTES=1048576
export LAYERLEAK_MAX_LAYER_BYTES=536870912
export LAYERLEAK_MAX_LAYER_ENTRIES=50000
export LAYERLEAK_MAX_MANIFEST_BYTES=0
export LAYERLEAK_MAX_CONFIG_BYTES=0
export LAYERLEAK_MAX_TAG_RESPONSE_BYTES=8388608
export LAYERLEAK_MAX_REPOSITORY_TAGS=0
export LAYERLEAK_MAX_REPOSITORY_TARGETS=0
export LAYERLEAK_REGISTRY_REQUEST_ATTEMPTS=2
# オプションのレジストリオーバーライド。通常は未設定のままにします。
export LAYERLEAK_REGISTRY_BASE_URL=
export LAYERLEAK_REGISTRY_AUTH_URL=
export LAYERLEAK_DATABASE_URL=postgres://postgres:postgres@localhost:5432/layerleak?sslmode=disable
同じ変数とそのデフォルト値は.env.exampleにあり、デフォルト値の信頼できる情報源です。
| 変数 | デフォルト | 目的 |
|---|---|---|
LAYERLEAK_LOG_LEVEL | info | ログレベル: debug、info、warn、error |
LAYERLEAK_FINDINGS_DIR | 未設定 | JSON検出結果ファイルを書き込む場所。未設定の場合、go.modを含む最も近い親ディレクトリの下のfindings/にデフォルト設定され、見つからない場合は現在の作業ディレクトリにフォールバックします。 |
LAYERLEAK_API_ADDR | 127.0.0.1:8080 | APIサーバーのバインドアドレス。コンテナイメージはこれを0.0.0.0:8080にオーバーライドします。 |
LAYERLEAK_PERSIST_RAW_SECRETS | 0 | 1に設定すると、生のシークレット値と生のコンテキストスニペットをディスクとPostgresに書き込みます。検出結果はデフォルトで編集されたままになります。 |
LAYERLEAK_HTTP_TIMEOUT | 30s | すべてのレジストリ呼び出し(マニフェスト、ブロブ、タグページ、認証トークン)に対するリクエストごとのタイムアウト。任意のGoの期間(30s、2m、1h)を受け入れます。 |
LAYERLEAK_MAX_FILE_BYTES | 1048576(1 MiB) | レイヤー内のファイルごとにバッファリングされる最大解凍バイト数。このサイズを超えるファイルは大きすぎるとしてスキップされます。ゼロより大きくなければなりません。 |
LAYERLEAK_MAX_LAYER_BYTES | 536870912(512 MiB) | レイヤーごとの最大解凍レイヤーストリームバイト数。0は制限を無効にします。 |
LAYERLEAK_MAX_LAYER_ENTRIES | 50000 | レイヤーごとの最大tarエントリ数。0は制限を無効にします。 |
LAYERLEAK_MAX_MANIFEST_BYTES | 0 | マニフェスト本体の最大バイト数。0は制限を無効にします。 |
LAYERLEAK_MAX_CONFIG_BYTES | 0 | イメージ設定本体の最大バイト数。0は制限を無効にします。 |
LAYERLEAK_MAX_TAG_RESPONSE_BYTES | 8388608(8 MiB) | レジストリのタグリスト応答ページあたりの最大バイト数。0は制限を無効にします。 |
LAYERLEAK_TAG_PAGE_SIZE |
MAX_*制限のいずれかを正の値に設定すると、それを超えるとスキャンが失敗し、作業を黙って切り詰める代わりに明確なエラーが返されます。
結果の動作:
findingsに残り、ゼロ以外のスキャン終了ステータスを生成します。total_findingsにはカウントされません。disposition、disposition_reason、line_numberが含まれ、トリアージと誤検出のレビューが容易になります。1で終了します。Layerleakには、migrations/の下にバージョン管理されたSQLマイグレーションが含まれています。
マイグレーションは意図的に手動で行われます。スキャナーはスキーマを自動生成または自動アップグレードしません。
Layerleakは、DBバックエンドのAPIとスキャナーの永続化にPostgreSQLサーバー>= 16.13を必要とします。
マイグレーションを順番にpsqlで適用します:
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0001_initial.up.sql
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0002_finding_occurrence_metadata.up.sql
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0003_scan_runs.up.sql
または、コンテナヘルパーコマンドを使用してマイグレーションを適用:
docker run --rm \
-e LAYERLEAK_DATABASE_URL="$LAYERLEAK_DATABASE_URL" \
ghcr.io/brumbelow/layerleak:latest \
layerleak-migrate-up
layerleak-migrate-upは、マイグレーションが既に適用されている場合でも安全に再実行できます。
部分的なマイグレーション状態を検出した場合、ゼロ以外のコードで終了し、手動介入を求めます。
ヘルパーはまた、サーバーバージョン>= 16.13を強制し、バンドルされているpostgresql-client-16がUbuntu PGDG 24.04パッケージ(.pgdg24.04+)でバージョン>= 16.13-1.pgdg24.04+1であることを検証します。
マイグレーションを逆順でロールバック:
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0003_scan_runs.down.sql
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0002_finding_occurrence_metadata.down.sql
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0001_initial.down.sql
運用上のデフォルト:
first_seen_atとlast_seen_atを持つ現在の重複排除状態を保持し、scan_runsに追加専用のスキャン履歴も保存します。(manifest_digest, fingerprint)によって正規に重複排除され、永続化の前に繰り返しの同一コンテキストスニペットが圧縮されます。シークレット安全性に関する注意:
LAYERLEAK_PERSIST_RAW_SECRETS=1の場合、Postgresは生の検出結果値と生のスニペットも保存します。scan_runs.result_jsonスナップショットは編集されたままです。CLIヘルプを表示:
layerleak --help
layerleak scan --help

サポートされている任意のレジストリ上の公開OCIイメージに対してスキャンを実行:
./layerleak scan ubuntu
./layerleak scan library/nginx:latest --format json
./layerleak scan alpine:latest --platform linux/amd64
./layerleak scan mongo
./layerleak scan ghcr.io/homebrew/core/hello:latest
./layerleak scan quay.io/prometheus/busybox:latest
./layerleak scan gcr.io/distroless/static:nonroot
./layerleak scan public.ecr.aws/docker/library/alpine:3.20
./layerleak scan mcr.microsoft.com/hello-world:latest

すべてのスキャンは、JSON検出結果ファイルを検出結果出力ディレクトリに書き込みます。
LAYERLEAK_FINDINGS_DIRが設定されていない場合、デフォルトの出力ディレクトリはgo.modを含む最も近い親ディレクトリ(通常はリポジトリルート)の下のfindings/で、リポジトリルートが見つからない場合は現在の作業ディレクトリにフォールバックします。
それらの保存された検出結果ファイルには、各検出結果についてredacted_value、編集されたcontext_snippet、正確なソース位置、ディスポジションメタデータ、および行番号を含む検出結果レコードが含まれます。
LAYERLEAK_PERSIST_RAW_SECRETS=1の場合、保存された検出結果ファイルには生のvalueとraw_context_snippetも含まれます。
Postgresの永続化が有効な場合、LAYERLEAK_PERSIST_RAW_SECRETS=1でない限り、生のfindings.valueとfinding_occurrences.raw_snippetは空のままです。
マルチアーキテクチャイメージの場合、layerleakはapplication/vnd.in-toto+jsonなどのアテステーションおよびプロベナンスマニフェストを、失敗したプラットフォームスキャンとしてカウントするのではなくスキップします。
ベアリポジトリ全体のスイープ:
mongoなどのベアリポジトリ名を渡すと、そのリポジトリ内のすべての公開タグを列挙し、各タグをダイジェストに解決し、重複するダイジェストをグループ化し、異なるターゲットをスキャンします。mongo:latestやmongo@sha256:...などの明示的なタグまたはダイジェストを渡してください。コマンド構文:
layerleak [command]
layerleak scan <image-ref> [flags]
リポジトリ全体のスイープ用のスコープフラグ(それぞれが単一のコマンドの対応する環境変数をオーバーライドします):
| フラグ | 目的 |
|---|---|
--tag-page-size | リポジトリ全体のスイープのためのレジストリタグリストページサイズ。ゼロより大きくなければなりません。LAYERLEAK_TAG_PAGE_SIZEをオーバーライドします。 |
--max-repository-tags | リポジトリ全体のスイープごとに列挙される最大タグ数。0は制限を無効にします。LAYERLEAK_MAX_REPOSITORY_TAGSをオーバーライドします。 |
--max-repository-targets | リポジトリ全体のスイープごとに解決される最大の異なるターゲット数。0は制限を無効にします。LAYERLEAK_MAX_REPOSITORY_TARGETSをオーバーライドします。 |
Layerleakはcmd/apiの下に最小限のJSON APIも含んでいます。
APIはPostgresバックエンドであり、LAYERLEAK_DATABASE_URLが必要です。ディスク上の検出結果ファイルからは提供しません。
次のように起動します:
go run ./cmd/api
または、APIコンテナを実行:
docker run --rm \
-p 8080:8080 \
-e LAYERLEAK_DATABASE_URL='postgres://<user>:<password>@<host>:5432/layerleak?sslmode=disable' \
ghcr.io/brumbelow/layerleak:latest
現在のエンドポイント:
GET /healthPOST /api/v1/scansGET /api/v1/scans/{id}GET /api/v1/repositoriesGET /api/v1/repositories/{repository}/scansGET /api/v1/repositories/{repository}/findingsGET /api/v1/findings/{id}GET /healthは{"status":"ok"}を返し、設定されたストアやスキャナーは必要ありません。
Kubernetesのreadiness probeやDocker Composeのhealthcheckターゲットに適しています。
POST /api/v1/scansは同期的です。referenceとオプションのplatformを含むJSONボディを受け入れ、Postgresの永続化が有効な場合はscan_run_idを返します。
APIスキャン応答は、CLI JSON出力と同じ編集された結果スキーマを再利用します。
GET /api/v1/scans/{id}は、永続化された実行メタデータと保存された編集された結果スナップショットを返します。
リポジトリと検出結果のエンドポイントも編集されたままです。redacted_valueと編集されたcontext_snippetを返し、Postgresからの生のシークレット値や生のスニペットは決して返しません。
GET /api/v1/repositories/{repository}/scansおよびGET /api/v1/repositories/{repository}/findingsは、オプションのregistryクエリパラメータ(例:?registry=ghcr.io)を受け入れます。省略された場合、下位互換性のためにレジストリはdocker.ioにデフォルト設定されます。これを使用して、GHCR、Quay、GCR、MCR、Amazon ECR Public、または任意のセルフホストレジストリ上のリポジトリのスキャンを取得します。
リストエンドポイント(/repositories、/repositories/{repository}/scans、/repositories/{repository}/findings)は、ページネーションのために?limit=と?offset=を受け入れます。limitのデフォルトは50で、最大200です。/repositories/{repository}/findingsは?disposition=actionable|suppressed|allも受け入れます。省略された場合、応答には実用的な検出結果のみが含まれます。
APIには認証が含まれていません。 組織内のデプロイでは、プライベートネットワーク上に保持し、独自の認証/認可ゲートウェイまたはリバースプロキシポリシーの前面に配置してください。
このリポジトリには、db、migrate、apiサービスを含むComposeスタックがdocker-compose.ymlに含まれています。
dbサービスのベースラインはpostgres:16.13-alpineに固定されています。
別のPostgresイメージを使用する場合は、サーバーバージョンを16.13以上に保ってください。
デプロイメント変数を設定します(シェルでエクスポートするか、docker-compose.ymlの隣に.envファイルに配置します):
export LAYERLEAK_IMAGE=ghcr.io/brumbelow/layerleak:latest
export LAYERLEAK_DB_NAME=layerleak
export LAYERLEAK_DB_USER=layerleak
export LAYERLEAK_DB_PASSWORD=replace-me
export LAYERLEAK_API_PORT=8080
デプロイ前にレンダリングされたCompose設定を検証:
docker compose config
APIを起動する前に、マイグレーションを一度実行します:
docker compose --profile manual run --rm migrate
APIサービスを起動:
docker compose up -d api
DockgeまたはKomodoで、同じComposeファイルをインポートし、長期実行されるapiサービスを有効にする前に、migrateサービスを一度実行します。
MITライセンスの下でリリースされています — LICENSEを参照してください。
このリポジトリがあなたの時間を節約したり、役に立った場合、今後の更新を支援することができます:
ありがとうございます :) これにより、プロジェクトのメンテナンスを続けるのに本当に役立ちます。
100 |
| リポジトリ全体のスキャン用のレジストリタグリストページサイズ。 |
LAYERLEAK_MAX_REPOSITORY_TAGS | 0 | リポジトリスキャンごとに列挙される最大タグ数。0は制限を無効にします。 |
LAYERLEAK_MAX_REPOSITORY_TARGETS | 0 | リポジトリスキャンごとに解決される最大の異なるターゲット数。0は制限を無効にします。 |
LAYERLEAK_REGISTRY_REQUEST_ATTEMPTS | 2 | 各レジストリリクエストの試行回数(最初の試行を含む)。 |
LAYERLEAK_REGISTRY_BASE_URL | 未設定 | オプションのオーバーライド。通常、layerleakは各イメージ参照からこれを導出します。プロキシや代替エンドポイントを介してスキャンを強制する場合にのみ設定します。 |
LAYERLEAK_REGISTRY_AUTH_URL | 未設定 | オプションのオーバーライド。通常、レジストリのWWW-Authenticateチャレンジから検出されます。 |
LAYERLEAK_DATABASE_URL | 未設定 | 設定されている場合、layerleakはスキャンをPostgresに書き込み、永続化が成功しないとコマンドは失敗します。 |