4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Gitleaks × pre-commit でシークレット混入を防ぐ

4
Last updated at Posted at 2026-05-04

はじめに

2026年5月、マネーフォワードがGitHub認証情報の不正アクセスを発表しました。流出したとされる情報には、ソースコード一式のほか、カード保持者370件の氏名・カード番号下4桁、そしてソースコードにハードコードされた各種認証キー・パスワードが含まれていました。

この事件の詳細な分析は こちらの記事 にまとめられており、シークレットがリポジトリに混入する主な経路として、以下が挙げられています。

  • .env ファイルを .gitignore に入れ忘れた誤コミット
  • CI/テストのフィクスチャに本番データを流用
  • バグ調査時のダンプファイルが削除されず残存
  • マイグレーションスクリプトへの直接埋め込み

Git履歴は特に注意が必要です。ファイルを削除しても、過去のコミット履歴には残り続けます。攻撃者が git log -p を実行するだけで、すべての履歴から認証情報を抽出できてしまいます。

では、コミットからpushまでの各フェーズで、どうすればシークレット混入を防げるのか?

本記事では、pre-commit(コミット前の早期検知)・CI(マージの門番)・Global Server Hooks(pushそのものをブロックする最終防衛ライン)の3層防御を Gitleaks で構築する手順を、安全なインストール方法とともに解説します。


安全なインストール手順

curl | bash を使ってはいけない理由

ツールのインストール手順として、次のような形式をよく見かけます。

# ❌ やってはいけない例
curl https://example.com/install.sh | bash

これは非常に危険です。理由は以下のとおりです。

  1. 内容を確認せずに実行している — ダウンロードとシェル実行が同時に行われるため、スクリプトの中身を人間が確認できません。
  2. 改ざんに気づけない — 配信サーバーやCDNが侵害されていた場合、悪意あるスクリプトがそのまま実行されます。
  3. サプライチェーン攻撃の入口になる — セキュリティツール自身がマルウェアの配布経路になった事例は実際に存在します。

セキュリティツールこそ、インストール方法を慎重に選ぶ必要があります。


前提

  • Git がインストールされていること
  • Python 3.8以上がインストールされていること(pre-commit に必要)
  • Linux / macOS 環境を想定(Windowsはパス等を適宜読み替えてください)

Step 1. Gitleaks をバージョン固定でインストール

公式の GitHub Releases からバイナリを直接取得します。バージョンを固定することで、予期しないアップデートによる挙動変化を防げます。

# バージョンを変数で管理する
GITLEAKS_VERSION="v8.24.3"

# ダウンロード(実行前にURLを確認してください)
curl -sSLO \
  "https://github.com/gitleaks/gitleaks/releases/download/${GITLEAKS_VERSION}/gitleaks_8.24.3_linux_x64.tar.gz"

ダウンロード後、必ずチェックサムを検証してから展開してください。

# チェックサムファイルも取得する
curl -sSLO \
  "https://github.com/gitleaks/gitleaks/releases/download/${GITLEAKS_VERSION}/checksums.txt"

# チェックサム検証
sha256sum --check --ignore-missing checksums.txt

問題がなければ展開してインストールします。

tar xzf gitleaks_8.24.3_linux_x64.tar.gz
sudo mv gitleaks /usr/local/bin/gitleaks
sudo chmod +x /usr/local/bin/gitleaks

# 動作確認
gitleaks version

企業環境では、公式バイナリを自社の内部レジストリにミラーして管理することをお勧めします。


Step 2. pre-commit をインストール

pip install pre-commit

# インストール確認
pre-commit --version

Step 3. .pre-commit-config.yaml を作成

リポジトリのルートに以下のファイルを作成します。

repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.24.3  # バージョンは固定する
    hooks:
      - id: gitleaks

rev はバージョンを固定してください。latest や main など可変なものは、意図しない変更が混入するリスクがあります。


Step 4. hook をインストール

pre-commit install

これで、git commit を実行するたびに Gitleaks がステージングされた差分を自動でスキャンします。


Step 5. 動作確認

全ファイルを対象にスキャンして、既存の混入がないかを確認します。

pre-commit run gitleaks --all-files

問題がなければ以下のように表示されます。

gitleaks...............................................................Passed

Step 6. (オプション)カスタムルールの設定

プロジェクト固有の機密情報パターンや、テスト用ダミー値の除外(allowlist)が必要な場合は、.gitleaks.toml を作成します。

[extend]
useDefault = true

[[rules]]
id = "custom-internal-token"
description = "社内独自トークン"
regex = '''MYAPP_[A-Z0-9]{32}'''
tags = ["token", "custom"]

[allowlist]
description = "テスト用ダミー値を除外"
regexes = [
  '''EXAMPLE_KEY_FOR_TESTING''',
]

pre-commit だけでは足りない理由

pre-commit は強力ですが、開発者がスキップできます。

# スキップの例(組織内での悪用に注意)
SKIP=gitleaks git commit -m "fix"

また、リポジトリを clone した開発者が pre-commit install を実行しなければ、hook 自体が動きません。

CI にも同じチェックを入れる

GitLab CI の場合は以下のように設定します。

# .gitlab-ci.yml
gitleaks:
  image: zricethezav/gitleaks:v8.24.3  # latestは使わない
  script:
    - gitleaks detect --source . --verbose --log-opts="--all"
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"

latest タグを避ける理由は3つあります。

  1. 再現性が失われる — latest は CI 実行のたびに異なるバージョンのイメージを引く可能性があります。「昨日は通ったのに今日は落ちる」という原因不明の挙動変化につながります。
  2. ルール変更による誤検知・見逃し — Gitleaks はバージョンアップのたびに検知ルールセットが更新されます。バージョンを固定しないと、ルール追加による突然の誤検知や、ルール変更による見逃しが発生しうる状態になります。
  3. サプライチェーンリスク — Docker Hub のイメージは latest タグが上書き可能なため、万一レジストリ側が侵害された場合に悪意あるイメージが流れ込むリスクがあります。インストール手順で curl | bash を避けた理由と同じ構造です。

ただし、push 時点でブロックするには CI では間に合いません。 CI はあくまで「main へのマージを防ぐ」層です。push そのものをブロックするには、後述する GitLab の Global Server Hooks が必要です。


push そのものをブロックする — Global Server Hooks

pre-commit も CI も、「開発者のローカル」または「マージ前」での検知です。push が GitLab サーバーに届いた時点で、すでにシークレットはリモートリポジトリに存在しています。

push を受け付ける前にブロックするには、GitLab Self-Managed の Global Server Hooks を使います。

公式ドキュメント: Server hooks | GitLab

Global Server Hooks は、GitLab サーバー上の特定ディレクトリにスクリプトを置くだけで、全リポジトリへの push に自動適用されます。Push Rules(GitLab UI で設定できる正規表現ブロック)と異なり、Gitleaks のような外部ツールを呼び出せるため、より高精度な検知が可能です。

設定ディレクトリ(Omnibus インストールの場合)

/var/opt/gitlab/gitaly/custom_hooks/pre-receive.d/

このディレクトリ配下に置いたスクリプトが、ファイル名のアルファベット順にすべての push に対して実行されます。

スクリプト例

#!/bin/bash
# /var/opt/gitlab/gitaly/custom_hooks/pre-receive.d/gitleaks.sh

while read oldrev newrev refname; do
  if [ "$oldrev" = "0000000000000000000000000000000000000000" ]; then
    range="$newrev"
  else
    range="$oldrev..$newrev"
  fi

  # 差分のみスキャン(全履歴スキャンは性能影響が大きいため避ける)
  git rev-list "$range" | while read commit; do
    git diff-tree --no-commit-id -p "$commit" | \
      gitleaks detect --pipe --no-git -v
    if [ $? -ne 0 ]; then
      echo "❌ 機密情報が検出されました。push をブロックします。"
      exit 1
    fi
  done
done
# 実行権限を付与する
chmod +x /var/opt/gitlab/gitaly/custom_hooks/pre-receive.d/gitleaks.sh

注意点

Global Server Hooks にはいくつかの制約があります。

  • タイムアウト制限がある — push 処理全体が長引くと push が失敗します。全履歴スキャンは避け、差分のみを対象にしてください。
  • Geo 環境ではセカンダリに複製されない — Geo レプリカを使っている場合、セカンダリノードには別途手動で配置が必要です。
  • Praefect クラスタでは全 Gitaly ノードへの配置が必要 — HA 構成の場合、すべてのノードにスクリプトを配置してください。
  • 設定はサーバー管理者のみ — GitLab の UI からは操作できません。

役割分担のまとめ

層 手段 強制力 対象
コミット前(ローカル) pre-commit + Gitleaks △ スキップ可能 個人の手元
push 時 Global Server Hooks ✅ サーバー側でブロック 全リポジトリ
MR マージ前 GitLab CI + Gitleaks ✅ マージをブロック main への混入防止

pre-commit は開発者体験を高める「早期検知」、CI は「マージの門番」、Global Server Hooks は「push そのものを止める最終防衛ライン」という役割分担で考えると整理しやすくなります。


まとめ

「混入してから対処する」ではなく、「混入させない仕組みを先に作る」ことが組織全体のセキュリティ水準を高める第一歩です。まず pre-commit を導入して開発者の手元での早期検知を習慣化し、次に CI・Global Server Hooks を加えてチーム全体の防御を固める、という順で段階的に整備することをお勧めします。

Gitleaks のインストールにあたっては、curl | bash を避け、バージョン固定とチェックサム検証を徹底してください。セキュリティツール自体がサプライチェーン攻撃の入口にならないよう、取得元の検証も重要です。

マネーフォワードの事件は、認証情報の管理とシークレットスキャンの重要性を改めて示しています。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?