0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIエージェント開発環境に秘密情報流出ゲートを自作して2週間運用したら誤警報ゼロだった話

0
Last updated at Posted at 2026-10-13

この記事の内容は、実際に2週間運用した結果に基づいています。完成品はOSSキットとして公開しています(cc-quality-gates)。

はじめに

AIコーディングエージェントに開発を任せていると、コミットが人間の手では追いつかないペースで積み上がります。筆者の環境では、並行して動く複数のエージェントセッションが30日で340コミット以上を積み上げます。

この状況で一番怖いのは、コードの品質でもバグでもなく、**「うっかり秘密情報(APIキー・トークン)を公開リポジトリにpushしてしまうこと」**です。一度公開されると、ボットが数分で拾って悪用されるため、削除では手遅れになります。

人間の目でレビューするのは物理的に不可能なので、公開の直前に自動で止める門番(ゲート)を自作しました。この記事は、その設計と2週間の運用実績の記録です。

結論(先に数字を)

項目 実績
運用期間 2週間(14日・push継続中に判定)
ゲートによる停止(block) 5件
うち正しい停止(真陽性) 5件(100%)
誤警報(誤block) 0件
全履歴スキャンでの検出 17件(うち実際の秘密は0件・ローテーション不要と判定)

「止めるべきものは確実に止め、無駄に止めない」——これが数値で確認できたので、本運用に昇格させ、キットとして公開しました。

設計:3層の門番

「1つの強い検知」に頼るのではなく、3つの役割を分担させる構成にしました。

[層1] pre-push hook …… 公開直前の関所(止める係)
[層2] GitHub Actions CI … 裏口対策(層1を迂回したpushも毎週全履歴を走査)
[層3] 人間のレビュー …… 文脈判定の委譲先(「これはテスト用ダミーか?」は機械に判断させない)

層1: push直前のフック

git push の直前に作動し、pushしようとしている差分だけを走査します(過去の全履歴を見ないので、昔のダミーデータで誤爆しません)。

探知機は次の2種類です。

  1. gitleaks(有名なOSS)——数百種類の既知パターンで「本物っぽい鍵の形」を検知
  2. 自作の単純パターン——token = "16文字以上..." のような代入形式を自前でも検知(gitleaksのルール更新ラグの対策)

検知したらpushをブロックし、どこで引っかかったかだけを表示します。値そのものは表示しない(ログにも残さない)ので、ゲート自身が情報漏洩源になることもありません。

層2: CIによる最終防衛線

hookは --no-verify で迂回できてしまう、という正直な限界があります。そこでGitHub Actionsでも全pushと毎週1回の全履歴走査をさせ、迂回pushがCIでfailすることをテストで実証しておきました。

層3: 文脈判定は機械に持たせない

ここが設計上の一番大事な判断です。

「この token = ... は本物か、テスト用のダミーか?」という文脈判断をhookに実装しない。

文脈判定をhookに入れると誤検知が温床になり、ゲートが生活を止めてしまいます(並行セッション5本が日常の環境では致命的)。そこでhookは単純パターンに限定し、止められたら人間が確認して、ダミーなら書き方を変えて再pushする運用にしました。「形式を変えろ」というブロックメッセージ自体が、「意図的ダミーであることの自己申告」を促します。

2週間の運用で起きたこと

導入から14日間、pushを続けながら観察しました。5件のblockが発生しましたが、内訳は:

  • テスト用のモック鍵(E2Eテストで意図的に書いたもの)——正しく停止。書き方を変えて再push
  • テストフィクスチャ内のダミートークン——正しく停止。同じく形式変更で解決

つまり、全部が「鍵っぽい文字列が本当に混ざっていた」ケースで、無駄止まりはゼロでした。逆に言うと、自分でも気づかないうちに「鍵の形をした文字列」が日常的にコミットに入ってくる——だから自動ゲートが必要、という実測でもあります。

合わせて、警告レベルの記録(68件)も全件レビューし、ブロックに昇格させるべきものがないことも確認しました。

キット化して公開した

2週間の実績を受けて、これを誰でも導入できるキットとして公開しました。

👉 github.com/fukukei23/cc-quality-gates

git clone https://github.com/fukukei23/cc-quality-gates.git
cd cc-quality-gates
bash scripts/setup.sh     # gitleaksのパス等を質問に答えて設定
bash scripts/selftest.sh  # 導入が正しく効いているか5項目で確認(PASS=5期待)

selftest.sh は単なる構文チェックではなく、モック鍵を実際にコミットしてhookが発火するかまで確認します。加えて「.gitleaks.toml の設定で検出を無効化されたらどうなるか」というバイパス耐性テストも入っています(gitleaks層を設定で無効化しても、自作パターン層が止める二重構造を確認できます)。

公開までに起きた実際のトラブル(読者への共有)

Linux(WSL2)では完璧に動いたキットが、Windowsでは5件の問題で動きませんでした。同じ悩みを持つ人のために、対応を残しておきます:

問題 対応
gitの改行コード自動変換(LF→CRLF)でbashスクリプトが構文エラー .gitattributes でスクリプトの改行をLF固定
Windowsは実行ファイルに .exe が付く セットアップ/テストで拡張子を自動解決
初めてのPCにはgitのユーザー設定が無くテストコミットが失敗 設定が無い場合のフォールバックを追加
対話式セットアップが一部のターミナル経由で動かない 環境変数による非対話モードを追加

(開発中に実装ミスで「存在するgitleaksまで .exe に書き換える」バグも作り込みましたが、テストが実動作で捕捉してくれました。テストは書いておいて損になりません)

既知の限界(正直な申告)

  • token2 = ... のような接尾語付き変数名は、単純パターン層を素通りします(正規表現の単語境界の問題・CI層のgitleaksは拾う可能性があります)。文脈判定を入れない設計方針の代償として、正直にREADMEに書いています
  • hook単体は --no-verify で迂回できます(最終防衛線はCI側)

まとめ

  • AIエージェントが大量にコミットする環境では、秘密情報のうっかり公開は「起こる前提」で対策すべき
  • 検知は1つの強いツールでなく、hook(止める)+ CI(裏口)+ 人間(文脈)の3層分担が現実的
  • 導入して終わりではなく、2週間の運用データ(真陽性5・誤警報0)で効いていることを数字で確認してから本運用に昇格した

キットはこちらからどうぞ。issue / PRも歓迎です。


※ この記事自体も、公開前に記事本文への機微スキャン(gitleaks)を通しています。ゲートを語る記事がゲートをすり抜けたら笑えないので。


本記事は個人Zennでも公開しています。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?