対象:個人開発・小規模運営でGitを使っていて、「APIキーをうっかりコミットしないか不安」という人。攻撃側の手口は扱わず、自分のリポジトリから秘密の流出を止める仕組みだけを扱います。
当サイトの視点:.gitignore だけでは秘密は守れない
「.envを.gitignoreに入れているから大丈夫」とよく言われますが、これには抜けがあります。.gitignoreは新しく追跡対象に入れないだけで、既にコミット済みの秘密や、急いでgit add -fで強制追加した秘密、.env.local.bakのような想定外のファイル名は捕まえられません。gitignoreが防げるのは事故の一部だけです。実際にコミット内容を見て「秘密らしい文字列」を検出する仕組み、つまり検出器が別に要ります。それがgitleaksの役割です。
なぜ「コミット前」で止めるのか
秘密が危険なのは、Gitが履歴を永久に保持するからです。最新のファイルから消しても、過去のコミットには残る。そしてpushされた瞬間、その履歴は他者の手元やサーバ、CIのログにも複製されます。
つまり秘密対策は、漏れた後の回収ではなく漏れる前の阻止が最も効きます。これは「公開ディレクトリに秘密を置き忘れない」棚卸し(→ webrootの棚卸し)と同じ発想を、コードに当てはめるものです。
どの段階で検出するか
秘密がコードから世界に出ていく経路には、2つの検査を置けます。手元のコミット時と、共有される直前(CI)です。
コード内の秘密
APIキー・鍵・トークン
検査1:pre-commit
コミット時にローカルで検出・中断
検査2:CI / cron
push後にマージ/デプロイ前で検出
公開・共有
ここまで来たら漏れた前提
gitleaksの組み込み方
まず既存の履歴をスキャンする
gitleaks git でスキャンする(v8.19.0より前の書き方では gitleaks detect)。過去のコミットに残っている秘密を洗い出すのが最初の仕事。ここで見つかったものは、後述のとおり失効が前提。pre-commitフックで1段目の検査を入れる
gitleaks git --pre-commit --staged(旧 gitleaks protect --staged)を走らせ、秘密を含むコミットをその場で中断する。pre-commitフレームワーク(.pre-commit-config.yaml)に追加すると、チームでもローカルでも同じ検査が掛かる。CI / cron で2段目の検査を入れる
gitleaks git を回し、すり抜けを捕まえる(→ 依存監査と同じく機械監視の発想)。誤検出は .gitleaks.toml で調整
.gitleaks.toml に書いて調整する。「警告を消す」のではなく「なぜ安全かを記録する」のが正しい運用。根拠のない除外は次の事故の原因になる。検出したら『失効』が先、履歴の書き換えは後
一度コミット・pushされた秘密を見つけたら、最優先はその鍵・トークンの失効と再発行(ローテート)です。git filter-repo 等で履歴から消すのは大事ですが、それは『これ以上広げない』ための後処理にすぎません。公開リポジトリ・フォーク・CIログ・他人のクローンに渡った秘密は回収不能と考え、まず無効化してから履歴をクリーンにしてください。順番を逆にすると、消している間に使われます。
.gitignore 頼み
- 新規の追跡しか防げない
- 既にコミット済みの秘密は検出できない
git add -fや想定外のファイル名に無力- 「入れたつもりがない」を検証できない
gitleaks(検出+失効運用)
- 作業ツリーと履歴の中身を実際に検査
- pre-commitとCIの二段で止める
- 検出したら失効までを手順化
- 誤検出は根拠を記録して除外
コマンドの使い分け(v8.19.0以降)
gitleaksはv8.19.0でコマンドが整理されました。古い detect と protect は今も動きますが非推奨で、ヘルプには表示されません。新しく組むなら次の3つを使います。
| コマンド | 調べる対象 | 主な使いどころ |
|---|---|---|
gitleaks git | Gitのコミット履歴 | 導入時の全履歴スキャン、CI、定期スキャン |
gitleaks git --pre-commit --staged | これからコミットする変更(ステージ済みの分) | pre-commitフック(公式フックの中身もこの形) |
gitleaks dir | フォルダやファイル(Gitで管理していないものも可) | 公開ディレクトリ、バックアップ、配布用のzipを展開したフォルダ |
gitleaks stdin | 標準入力で渡した文字列 | 他のコマンドの出力やログを流し込んで調べる |
検出が1件以上あると終了コード1を返し、何もなければ0を返します。CIやcronでは、この終了コードで失敗扱いにできます。出力には --redact を付け、見つかった秘密そのものがログに残らないようにします。
設定例:pre-commitフックとGitHub Actions
pre-commitフレームワークを使う場合は、リポジトリの直下に次のファイルを置きます。rev は使う時点の最新リリースに合わせます(2026年10月時点の最新はv8.30.1)。
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1
hooks:
- id: gitleaksid は、Goで組み立てる gitleaks のほかに、Dockerで動かす gitleaks-docker、PCに入れ済みのgitleaksを使う gitleaks-system も選べます。ファイルを置いたら、各自の手元で次を実行します。
pip install pre-commit # pre-commit本体を入れる
pre-commit install # このリポジトリにフックを登録する(クローンごとに1回)
pre-commit run --all-files # 登録直後に、全ファイルを一度検査する
pre-commit autoupdate # 時々実行して、rev を新しいリリースに上げるGitHubでCIを回すなら、公式のGitHub Actionが使えます。履歴全体を調べるため、チェックアウトでは fetch-depth: 0 を指定します。
# .github/workflows/gitleaks.yml
name: gitleaks
on:
pull_request:
push:
schedule:
- cron: "0 4 * * *"
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}組織アカウントのリポジトリでは、このActionにライセンスキー(GITLEAKS_LICENSE)が必要です。公式の説明では、gitleaks.ioで申し込めば無料で発行され、個人アカウントのリポジトリでは不要とされています。自前のGitサーバーやGitHub以外のCIなら、ジョブの中で gitleaks git --redact を直接実行すれば同じことができます。
どこで検査するか:4つの場所の比較
1か所だけでは抜け道が残ります。それぞれが何を止め、どこに穴があるかを並べると、組み合わせる理由が分かります。
| 検査の場所 | 止められる時点 | 調べる範囲 | 抜け道・限界 |
|---|---|---|---|
| pre-commitフック(手元) | コミットする前 | ステージした変更 | git commit --no-verify や SKIP=gitleaks で飛ばせる。クローンしただけではフックは入らない |
| CI(GitHub Actionsなど) | マージ・デプロイの前 | pushされたコミットと履歴 | push自体は済んでいる。公開リポジトリなら、その時点で漏れた前提 |
| 定期スキャン(cron) | 後から見つける | リポジトリ全体の履歴 | 発見までに時間差がある。ルール更新で新しく見つかる分を拾える |
| GitHubのプッシュ保護 | GitHubへのpush時 | GitHubが対応する種類の秘密 | 理由を選べば回避できる。GitHub以外のサーバーには効かない |
GitHubのプッシュ保護は、個人ユーザー向けには公開リポジトリへのpushで既定で有効になっています。無料で効く安全網ですが、手元のコミットは止めず、対応していない形式の鍵や自作の接続文字列は通ることがあります(詳しくは GitHubに公開された認証情報が今も有効な理由)。gitleaksは、その手前と、GitHubの外を受け持ちます。
自分の環境で確認する方法
導入済みのつもりでも、実際に動いているとは限りません。自分のリポジトリで、次を順に確かめます。
gitleaksのバージョンを確かめる
gitleaks version を実行します。v8.19.0より古いと gitleaks git などの新しいコマンドが使えないので、更新します。
フックが登録されているか確かめる
.git/hooks/pre-commit があるかを見ます。git config --get core.hooksPath で別のフォルダが設定されている場合は、そちらを見ます。Gitの仕様上、フックはクローンで複製されないので、新しいPCや新しいクローンでは pre-commit install を実行し直します。
履歴全体を一度スキャンする
リポジトリの直下で gitleaks git --redact -v を実行します。検出が0件なら終了コードは0です。見つかった場合は、出力されたファイル名とコミットをもとに、その鍵がまだ有効かを発行元の管理画面で確かめます。
Gitの外にあるフォルダも調べる
デプロイ先の公開フォルダ、バックアップ、配布用に作ったzipの中身は、Gitの履歴スキャンでは見えません。gitleaks dir (フォルダのパス) --redact で調べます(→ 公開ディレクトリの棚卸し)。
.envが一度でもコミットされていないか確かめる
git log --all --oneline -- .env で、過去に .env を含むコミットがあったかを確認します。1行でも出たら、その時点の中身は履歴に残っています。
誤検出の扱い方
テスト用のダミー鍵やドキュメントの例が検出されることはよくあります。除外の方法は3つあり、範囲の狭い順に使います。
- 行単位:その行に
gitleaks:allowというコメントを書く - 検出結果単位:出力に表示される識別子(フィンガープリント)を、リポジトリ直下の
.gitleaksignoreに書く(公式には実験的な機能とされています) - ファイルやパターン単位:
.gitleaks.tomlの許可リストに書く
.gitleaks.toml を自分で作るときは、[extend] に useDefault = true を書いて既定のルールを引き継ぎます。これを書かずに自作のルールだけを置くと、既定のルールで拾えていた鍵が検出されなくなります。
古いリポジトリで既存の検出が多い場合は、--baseline-path に過去のレポートを渡すと、新しく増えた分だけを報告させられます。ただし、基準にする前に、そこに含まれる鍵は失効させておきます。基準に入れることは、鍵を安全にすることではないからです。
よくある間違いと直し方
- フックを設定ファイルに書いただけで安心する:
pre-commit installを実行しないと動きません。各自が実行し、CIでも同じ検査を回して二重にします。 --no-verifyで検査を飛ばすのが習慣になる:飛ばしても、CIの検査をマージの必須条件にしておけば止まります。- CIのログに秘密をそのまま出す:
--redactを付けます。CIのログも、閲覧できる人が多い場所です。 - CIで浅いクローンのまま検査する:最新のコミットしか見ないため、履歴の秘密を見落とします。
fetch-depth: 0を指定します。 - 履歴から消して終わりにする:GitHubの公式手順も、まず失効・差し替えを最初の手順にしています。フォークやクローン、キャッシュに残った分は消せません。
- 本物の鍵を「誤検出」として許可リストに入れる:除外の理由をコメントに書き、レビューで確認します。
実際の事例:公開されたままのアクセスキー
トヨタ自動車は2022年10月7日、コネクティッドサービス「T-Connect」の利用者向けサイトについて、ソースコードの一部がGitHub上で公開状態になっていたと発表しました。同社の発表によると、経緯は次のとおりです。
- 2017年12月、サイトの開発委託先が、ソースコードの一部を誤って公開設定のGitHubアカウントにアップロードした
- そのソースコードに、顧客情報を保存するデータサーバーへのアクセスキーが含まれていた
- 2022年9月15日に非公開にし、9月17日にアクセスキーを変更した
- 対象はメールアドレスと顧客管理番号の296,019件。アクセス履歴から第三者の利用は確認できなかったが、完全には否定できないとしている
公開から非公開までは約5年です。この事例は、自社の管理するリポジトリの外、つまり委託先のアカウントで起きました。自分のリポジトリにgitleaksを入れるだけでは届かない場所があるので、キーそのものの権限を絞り、定期的に差し替える運用も合わせて必要です。また、同社も公開を止めた2日後にキーを変更しています。見つけたらキーを替える、という順番はこの事例でも同じです。
非公開のリポジトリでも安心はできません。2026年のCAMPFIREの事案では、同社の発表によれば、不正利用されたGitHubの認証情報を起点に、GitHub上で閲覧できた情報からクラウドの認証情報が取得されました(→ CAMPFIREの不正アクセス)。非公開のリポジトリにも秘密を置かず、gitleaksで定期的に確かめておく理由になります。
当サイトはどうしているか
当サイトは、そもそも秘密をGitに一切入れない設計を基本にしています。接続情報やAPIキーはサーバ上の保護された設定(権限を絞った環境ファイル)にだけ置き、リポジトリにも引き継ぎ資料にも平文では残しません(→ 秘密をgitに入れない/自前Git vs GitHub)。その上で、人間は必ずミスする前提で検出器を重ねます。設計で「入れない」を担保し、gitleaksのようなスキャンで「入ってしまった」を捕まえる——この二層が、秘密漏えいに対する当サイトの守りです。秘密の扱いの原則そのものは .envと秘密情報 や パスワードの安全な保管 とも共通しています。
次に読む
- GitHub の設定:GitHub の2段階認証(2FA)の設定方法
- 入門:.envとAPIキーは何が危なくて、どう守るのか
- GitHubの認証情報からの侵入:CAMPFIREの不正アクセス(2026年)
- 漏らした後の対応:GitHubに公開された認証情報54万件が今も有効——削除ではなく失効が必要な理由
- AIエージェントによる侵入:Hugging Faceへの侵入(2026年):AIエージェントが自律的に攻撃した事案
- 棚卸し:公開ディレクトリに秘密を置き忘れていないか
- 自前運用:秘密をgitに入れない/自前Git vs GitHub
- 用語:「.env」とは — 環境変数ファイルが漏れると何が起きるか
- ツール:シークレット漏れ検出(貼り付けて検査)
出典
- gitleaks(公式リポジトリ)README:コマンド(git・dir・stdin)、v8.19.0での detect/protect の非推奨化、終了コード、
--redact、gitleaks:allow、.gitleaksignore、--baseline-path、設定の継承 — github.com/gitleaks/gitleaks / 公式フックの定義 — .pre-commit-hooks.yaml / リリース一覧 — Releases - gitleaks-action(公式GitHub Action)README:ワークフロー例とライセンスキー — github.com/gitleaks/gitleaks-action
- pre-commit 公式ドキュメント(install・run --all-files・autoupdate・SKIP) — pre-commit.com
- Git 公式ドキュメント「githooks」(pre-commitフックと --no-verify、フックの配置) — git-scm.com
- GitHub Docs「プッシュ保護について」 — docs.github.com /「リポジトリからの機微なデータの削除」 — docs.github.com
- トヨタ自動車「お客様のメールアドレス等の漏洩可能性に関するお詫びとお知らせについて」(2022年10月7日) — global.toyota