2026年7月21日
2026年7月21日
Secretの漏洩防止スキャンをCIに組み込む方法(WordPress開発向け)
データベースのパスワードや API キーが Git に入ってしまう事故は、コミット前のフックと CI のシークレットスキャンを組み合わせると、公開される前に止められる可能性が高くなります。この記事では、WordPress のテーマ・プラグイン・サイト一式を Git で管理しているプロジェクトを例に、Gitleaks を中心としたスキャンを GitHub Actions に組み込む手順、誤検出の扱い、見つかったときの対応までを説明します。
なぜ CI でスキャンするのか
WordPress の開発では、秘密情報がコードに紛れ込む経路がいくつもあります。
- wp-config.php のデータベース接続情報や認証用キー・ソルト
- 決済、メール送信(SMTP)、外部 API 用のキーを、テーマの functions.php やプラグインに直接書いたもの
.envファイル、デバッグ用に書き出したログ、データベースのダンプファイル
一度コミットした秘密情報は、後のコミットで消しても履歴に残ります。リポジトリが公開されていれば、自動で収集するツールに短時間で見つかることもあります。そのため、まず .gitignore で入れない仕組みを作り、それでも漏れたものをスキャンで止める、という二段構えにします。
スキャンを置く場所は3つあり、役割が異なります。
- コミット前フック(開発者の手元): 最も早く止められますが、
--no-verifyで飛ばせ、入れていない人には効きません。 - CI(プルリクエストと push ごと): 全員のコミットを同じ条件で確認でき、ブランチ保護で必須チェックにすればマージを止められます。
- 定期的な全履歴スキャン: スキャナーのルールが更新されると、過去のコミットから新たに見つかることがあります。
この記事の中心は2ですが、1と3も合わせて設定します。
まず .gitignore と秘密情報の置き場所を整える
スキャンは最後の網です。先に、秘密情報をリポジトリの外に置く形にしておきます。
# WordPress
wp-config.php
.env
.env.*
!.env.example
wp-content/debug.log
wp-content/uploads/
*.sql
*.sql.gz
秘密情報は、サーバー上の wp-config.php(Git 管理外)に定数として書くか、Web からアクセスできない場所に置いた .env から getenv() などで読み込みます。リポジトリには、値をダミーにした .env.example や wp-config-sample.php だけを置きます。ダミー値は your-api-key のように、本物と取り違えない形にしてください。
Gitleaks を手元で試す
Gitleaks は、正規表現とエントロピー(文字列のランダムさ)を使って秘密情報らしい文字列を探すオープンソースのツールです。主要なクラウドや SaaS の API キー形式のルールが標準で入っています。
手元にインストールしたら、まずリポジトリの全履歴を一度スキャンして現状を把握します。
# Git の全履歴をスキャン(結果の秘密情報部分は伏せて表示)
gitleaks git --redact -v .
# 作業ディレクトリのファイルだけをスキャン(Git 管理外のファイルも含む)
gitleaks dir --redact -v .
Gitleaks v8 の新しい版ではサブコマンドが git と dir に整理されました。古い版の detect や protect も記事や設定例に多く残っているので、使っている版の gitleaks --help で確認してください(2026年10月現在)。--redact を付けると、検出結果に秘密情報そのものが表示されません。CI のログは多くの人が見られるため、CI でも常に付けておきます。
検出がなければ終了コード0、検出があれば1で終わるので、CI ではこの終了コードで失敗を判定します。
GitHub Actions に組み込む
公式アクションを使う方法
Gitleaks には GitHub Actions 用のアクションがあります。
# .github/workflows/secret-scan.yml
name: Secret scan
on:
pull_request:
push:
branches: [main]
workflow_dispatch:
schedule:
- cron: '0 18 * * 0' # 毎週の全履歴スキャン(UTC)
jobs:
gitleaks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 履歴をすべて取得する
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} # 組織アカウントで必要な場合
fetch-depth: 0 を忘れると、チェックアウトが最新コミットだけになり、プルリクエストに含まれる途中のコミットを確認できません。このアクションは、組織アカウントのリポジトリではライセンスキーが必要とされています(2026年10月現在)。条件は変わることがあるため、利用前にアクションの README を確認してください。ワークフローの permissions を絞る場合も、必要な権限は README で確認します。
CLI を直接実行する方法
アクションを使わずに、リリースページのバイナリを取得して実行することもできます。
- name: Run gitleaks
run: |
GITLEAKS_VERSION=8.28.0 # 例。最新版はリリースページで確認する
curl -sSfL -o gitleaks.tar.gz \
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
tar -xzf gitleaks.tar.gz gitleaks
./gitleaks git --redact -v .
バージョンは固定し、更新は意図して行います。リリースページにはチェックサムも公開されているので、取得したファイルを検証する手順を加えるとより安全です。
最後に、GitHub のブランチ保護(またはルールセット)で、このジョブを必須のステータスチェックに指定します。これで、検出があるプルリクエストはマージできなくなります。
コミット前フックを設定する
pre-commit フレームワークを使っている場合は、.pre-commit-config.yaml に追加します。
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.28.0
hooks:
- id: gitleaks
pre-commit install を実行すると、ステージした変更だけがコミット時にスキャンされます。husky を使っているプロジェクトなら、.husky/pre-commit に Gitleaks のステージ済み変更のスキャンを書く方法もあります。
誤検出とプロジェクト固有ルールの扱い
スキャンを入れると、テスト用のダミーキーやサンプルファイルが検出されることがあります。対応の考え方は次のとおりです。
- 明らかなダミー値: 該当行の末尾に
gitleaks:allowというコメントを付けると、その行は無視されます。 - 特定の検出結果を除外する: 検出結果に表示されるフィンガープリントを
.gitleaksignoreに書きます。 - 既存リポジトリに導入する: 過去の検出をすべて直すまで CI を止めたくない場合、現状のレポートを基準(ベースライン)として保存し、それ以降の新しい検出だけで失敗させる方法があります。ただし、過去の検出も本物かどうかの確認は別途行ってください。
WordPress 固有の書き方を追加で検出したい場合は、.gitleaks.toml にルールを足します。
title = "wp project gitleaks config"
[extend]
useDefault = true # 標準ルールを残したまま追加する
[[rules]]
id = "wp-config-db-password"
description = "wp-config 形式で直書きされた DB パスワード"
regex = '''define\(\s*['"]DB_PASSWORD['"]\s*,\s*['"][^'"]{8,}['"]\s*\)'''
keywords = ["db_password"]
[allowlist]
description = "サンプルファイルは除外"
paths = ['''wp-config-sample\.php$''']
除外設定の書き方([allowlist] か、新しい版の [[allowlists]] か)は Gitleaks の版によって異なるので、使う版のドキュメントに合わせてください。除外を増やしすぎると網の目が粗くなるため、除外は理由をコメントに残し、レビューで確認する運用にします。
ほかの選択肢
- TruffleHog: 検出したキーが実際に有効かどうかを、提供元の API に問い合わせて確かめる機能があります。誤検出を減らせる一方、外部への問い合わせが発生する点は理解したうえで使います。
- GitHub のシークレットスキャン: GitHub 自体が既知の形式のキーを検出し、プッシュ保護を有効にすると push の時点で止められます。公開リポジトリとプライベートリポジトリで使える範囲が異なり、プランによって条件が変わるため、GitHub のドキュメントで現在の提供範囲を確認してください。
複数を併用しても構いません。検出できる形式はツールごとに違うため、1つのツールで漏れがゼロになるわけではありません。
検出されたときの対応
本物の秘密情報が検出されたら、「公開されたもの」として扱います。履歴から消しても、すでにクローンやフォーク、キャッシュに残っている可能性があるためです。
- まず無効化・再発行する: API キーは提供元の管理画面で失効させて新しいキーを発行し、データベースのパスワードは変更します。WordPress の認証用キーとソルトを変えると、ログイン中の全ユーザーがログアウトされるので、作業の時間帯に注意してください。
- 新しい値をリポジトリ外に移す: wp-config.php や
.env、CI の Secrets に置き、コードからは参照だけにします。 - 必要に応じて履歴から削除する: git filter-repo などで履歴を書き換えると、全員がクローンし直す必要があります。無効化を済ませたうえで、影響を見て判断します。
- アクセスログを確認する: 漏れていた期間に不審な利用がなかったか、提供元のログやサーバーのログを確認します。
まとめ
- 秘密情報はまず
.gitignoreとリポジトリ外の設定で入れない形にし、スキャンは最後の網として使います。 - Gitleaks は
gitleaks git --redactで履歴をスキャンでき、検出時の終了コードで CI を失敗させられます。サブコマンドや設定の書き方は版で確認します。 - GitHub Actions では
fetch-depth: 0で履歴を取得し、ブランチ保護で必須チェックにします。週1回の全履歴スキャンも加えます。 - 誤検出は
gitleaks:allowや.gitleaksignoreで個別に扱い、除外の理由を残します。 - 本物が見つかったら、削除より先にキーの無効化と再発行を行います。