結論
-
.envや鍵をコミットしてから消すのは大変です(前回の記事)。コミットの手前で止めるなら、gitleaks を pre-commit フックに入れるのが手軽でした。偽の GitHub トークンを含む.envは、フックでコミットが止まりました(筆者の環境で確認)。 - ただし、gitleaks はトークンの形をした値を探す道具で、
.envというファイルそのものは止めません。DB_PASSWORD=...のような平文のパスワードだけの.envはそのまま通りました(筆者の環境で確認)。ファイル名のチェックを数行足すと止まりました。 -
git commit --no-verifyを付けるとフックは飛ばされます(git公式・実機とも確認)。AIエージェントにコミットを任せるなら、GitHub の push protection も合わせて使うのが安全です。
この記事は「AIエージェントと秘密情報」の検証シリーズです。新しい検証は X(@supportapp3_lab)でもお知らせしています。
この記事は、AIエージェントと秘密情報の話の続きです。エージェントに git add . と git commit を任せると、.gitignore の漏れがそのまま履歴に入ります。前回は入ってしまった後の探し方と消し方を確かめたので、今回は入る前に止める側を確かめます。
検証環境と範囲
- Debian 13 / git 2.47.3 / gitleaks 8.30.1(GitHub Releases のバイナリ。checksums.txt で sha256 を確認)
- 使い捨てのローカルリポジトリだけで確かめました。GitHub への push はしていません。
- トークンはランダムに作った偽物、パスワードはダミー文字列です。出力の値は gitleaks の
--redactで伏せています。
1. gitleaks でステージ済みの変更を調べる
ステージした .env に、偽の GitHub トークン(ghp_ で始まる形)、偽の OpenAI キー(sk-proj- で始まる形)、DB_PASSWORD=dummy-not-a-secret を書いて試しました。
git add .env
gitleaks git --pre-commit --staged --redact -v .
echo "exit=$?"
結果(抜粋):
Finding: GITHUB_TOKEN=REDACTED
RuleID: github-pat
File: .env
Line: 1
Finding: OPENAI_API_KEY=REDACTED
RuleID: generic-api-key
File: .env
Line: 2
WRN leaks found: 2
exit=1
- GitHub トークンは専用のルール(
github-pat)、OpenAI 形式の偽キーは汎用のルール(generic-api-key)で見つかりました。 - 3行目の
DB_PASSWORD=dummy-not-a-secretは検出されませんでした。 - 見つかると終了コードが 1 になります。これをフックに使います。
2. pre-commit フックに入れる
いちばん簡単なのは、.git/hooks/pre-commit に直接書く方法です。
#!/bin/sh
gitleaks git --pre-commit --staged --redact --no-banner . || {
echo "gitleaks: 秘密情報らしき値が見つかったのでコミットを止めました" >&2; exit 1; }
chmod +x .git/hooks/pre-commit
git commit -m "add env"; echo "exit=$? HEAD=$(git log --oneline -1)"
WRN leaks found: 2
gitleaks: 秘密情報らしき値が見つかったのでコミットを止めました
exit=1 HEAD=2332163 init
コミットは作られず、HEAD は最初のコミットのままでした(筆者の環境で確認)。
チームで共有したい場合は、gitleaks の README に pre-commit フレームワーク 用の設定例があります(repo: https://github.com/gitleaks/gitleaks、id: gitleaks)。また、git config core.hooksPath <ディレクトリ> でフックの置き場所をリポジトリ内のディレクトリに変えることもできます(git公式)。この2つは今回は試していません。
3. 平文パスワードだけの .env は通る
次に、トークンの形をしていない値だけの .env を試しました。
DB_PASSWORD=dummy-not-a-secret
SECRET_KEY=change-me-dummy
INF no leaks found
[main f652d7e] plain env
1 file changed, 2 insertions(+)
create mode 100644 .env
gitleaks のフックがあっても、コミットされました(筆者の環境で確認)。gitleaks は値の形やルールで判定するので、.env というファイル名だけでは止めません。実際のパスワードがダミーと同じように「形のない文字列」なら、同じく通る可能性が高いです(推測)。
4. ファイル名のチェックを足す
.env と .env.local などはファイル名で拒否し、.env.example などのひな形だけ通すようにしました。
#!/bin/sh
if git diff --cached --name-only --diff-filter=ACMR \
| grep -E '(^|/)\.env($|\.)' \
| grep -vE '\.env\.(example|sample|template)$'; then
echo "上の .env ファイルはコミットしません(.gitignore に追加してください)" >&2
exit 1
fi
gitleaks git --pre-commit --staged --redact --no-banner . || exit 1
.env
上の .env ファイルはコミットしません(.gitignore に追加してください)
exit=1 HEAD=2332163 init
.env は止まり、同じ中身の .env.example はコミットできました(筆者の環境で確認)。.env.example に本物の値を書いてしまった場合は、このファイル名チェックでは止まりません。トークン形式なら gitleaks の側で止まります。
5. --no-verify でフックは飛ばされる
フックはローカルの仕組みなので、飛ばすこともできます。
git commit -q --no-verify -m "add env (no-verify)"; echo "exit=$? HEAD=$(git log --oneline -1)"
exit=0 HEAD=7f6e444 add env (no-verify)
偽トークン入りの .env がそのままコミットされました(筆者の環境で確認)。git の公式ドキュメントにも、--no-verify は pre-commit と commit-msg のフックを飛ばすと書かれています。pre-commit フレームワーク経由なら、SKIP=gitleaks でも飛ばせます(gitleaks README)。
AIエージェントにコミットを任せる場合、エージェントがフックの失敗を見て --no-verify を付け直すことがあり得ます(推測。今回、エージェントでは試していません)。エージェントの指示や設定で --no-verify を禁止しておくと安心です。
6. ローカルの次の守り:GitHub の push protection
GitHub には、push の時点で秘密情報を止める push protection があります(GitHub公式)。
- ユーザー向けの push protection は GitHub.com で既定で有効で、公開リポジトリへの secret の push を止めます。
- リポジトリ向けの push protection は既定で無効で、GitHub Secret Protection が必要です。
- どちらも、理由を指定して bypass(通過させる)ことができます。
フックはローカルで飛ばせるので、サーバー側のこの仕組みと二重にしておくのがよさそうです。ただし、どちらもトークンの形で判定する点は同じなので、平文のパスワードや .env そのものを止めたいなら、4章のファイル名チェックと .gitignore が要になります(推測を含みます)。
7. すでにコミットしていないか、履歴も調べる
gitleaks は履歴全体も調べられます。トークンを含むファイルをコミットし、次のコミットで削除したリポジトリで試しました。
gitleaks git --redact .
gitleaks git --redact -r - -f csv . | cut -d, -f1-6
INF 3 commits scanned.
WRN leaks found: 1
RuleID,Commit,File,SymlinkFile,Secret,Match
github-pat,8b30c2504d762f0f9d54c612746ffb98cbde0cab,config.txt,,REDACTED,REDACTED
いまはもう無いファイルでも、どのコミットに入っていたかが分かりました(筆者の環境で確認)。見つかった場合は、まず鍵を再発行してから、前回の記事 の手順で履歴から消してください。
まとめ
- gitleaks の pre-commit フックで、トークン形式の値を含むコミットは止まった(実機)。
- 平文パスワードだけの
.envは通った。ファイル名のチェックを足すと止まった(実機)。 -
--no-verifyでフックは飛ばされる(実機・git公式)。GitHub の push protection と二重にする(公式)。
AIエージェントの側では、次の設定も合わせて行ってください。
- Claude Code: settings.json の permissions.deny
- Codex CLI: permission profile の deny
- どのエージェントが
.envを読めそうかの点検: ファイル名だけで点検する日本語CLI
関連記事:
- 過去にコミットした.envはgitの履歴から読める:見つけ方と git-filter-repo での消し方
- Codex CLIに.envを読ませない設定:公式例の "**/*.env" だけでは .env.local と深い階層が読めた
- Claude Codeに.envを読ませない設定は settings.json の permissions.deny に書く
参考(公式):
- gitleaks(gitleaks/gitleaks)
- git-commit ドキュメント(--no-verify)
- githooks ドキュメント(core.hooksPath)
- Push protection – GitHub Docs
※ 仕様は 2026-10-20 時点の公式ドキュメントに基づきます。検証は git 2.47.3 / gitleaks 8.30.1 で、Linux の使い捨て環境でのみ行いました。
更新情報やちょっとしたTipsは X(@supportapp3_lab)で発信しています。