なぜGit commitに機密情報(APIキー/パスワード)を含めてはいけないのか?履歴に残るリスクを攻撃視点で理解する

この記事の主題は「Git commit に機密情報を入れると、なぜ危険なのか」です。結論からいきます。


結論(先に要点)

  • Git は履歴を保持する仕組みなので、機密情報を一度コミットすると 過去のコミットに残り続ける可能性があります(ファイルを消して再コミットしても、履歴までは消えません)。
  • さらに、リポジトリは複製されます(clone / fork / CI のチェックアウト等)。どこかに一度出た秘密は回収が難しいため、漏洩の影響が広がります。
  • もしコミットしてしまったら、最優先は 失効(revoke)/ローテーション(「削除」より先)。履歴の書き換えは副作用も大きいので、必要性と影響範囲を確認してから行います。
  • 予防が最強です。.gitignore、フック、CI スキャン、push protection で「そもそも入れない」を作ります。

漏洩すると何が起きるか

公開されたキーは「すぐに攻撃対象」になり得る

API キーやアクセスキーが Git の履歴に含まれてしまうと、第三者がその文字列を入手できる状態になります。 特に公開リポジトリでは、コミット履歴を含めて誰でも取得できるため、漏洩した認証情報が悪用される可能性が高まります。

GitHub の secret scanning は、リポジトリ内のシークレットを検出するために「全ブランチの Git 履歴全体」をスキャンすると説明されています(アーカイブされたリポジトリも対象)。 つまり「過去のコミットに一瞬だけ入った」秘密でも検出・悪用の対象になり得ます。

典型的に起こり得る被害

漏洩した認証情報が有効なままだと、次のような被害につながります。

  • サービスや管理画面への不正アクセス(あなた/組織の権限で操作される)
  • クラウドリソースの不正利用(コスト発生・リソース枯渇)
  • データベース・ストレージ等の情報漏洩、改ざん
重要なのは「削除したから安全」ではない点です。漏洩に気づいた時点で、失効(revoke)/ローテーション を最優先に考える必要があります。

具体的な攻撃シナリオ(攻撃者の視点で理解する)

公開リポジトリの自動スキャン

公開リポジトリは、誰でもクローンでき、差分や履歴も取得できます。 そのため攻撃者は、公開データを対象に機械的にシークレットを探索し、見つかったものを試行します。

補足として、GitHub では secret scanning が コミット(Git履歴) を対象にスキャンし、検出時にアラートを生成する仕組みを提供しています。

CI/CD(例:GitHub Actions)経由の漏洩

シークレットは「コードに直書き」だけでなく、CI/CD の実行時に環境変数として渡されることも多いです。 このとき、ワークフローのログ出力、テスト用のデバッグ出力、あるいは不審な変更によって、意図せず外部へ流出するリスクがあります。

プライベートリポジトリでも起こり得る経路

プライベートでも、次のような要因で漏洩します。

  • 端末・IDE の侵害(ローカルに保存した .env や設定ファイルが抜かれる)
  • 侵害されたアカウントによるリポジトリ閲覧
  • ログや成果物(ビルド成果物、テストレポート)へのシークレット混入

うっかりコミットしてしまったら(優先順位つき対応)

機密情報を含むコミットに気づいたら、「履歴から消す」より先にやるべきことがあります。 GitHub のドキュメントでも、シークレット(パスワード・トークン・資格情報など)の場合、最初の手順として失効/ローテーションが必要と明記されています。

1) まず失効(revoke)/ローテーション(最優先)

漏洩した認証情報は「すでに取得されている前提」で扱うのが安全です。

  • 発行元の管理画面で無効化 → 再発行
  • パスワードなら変更、鍵なら作り直し

この時点で、多くのリスクは大きく低減できます。

2) 露出範囲の確認(どこに入ったか)

  • どのファイル・どのコミットに入ったか
  • どのブランチ/タグに含まれるか
  • すでに公開(push)されたか、PR に載ったか

3) リポジトリからの削除(“最新”だけでは不十分)

ファイルを削除して再コミットしても、過去の履歴に残ります。 完全に消す必要がある場合は、履歴の書き換えが必要です。

GitHub は「機微なデータを履歴から削除する」手段として git-filter-repo を紹介し、履歴の書き換えが複雑で副作用が多いこと(再汚染、コミットハッシュ変更、PR diff への影響など)も強調しています。

4) 履歴を書き換えるなら、手順と影響を“チームで”管理する

履歴の書き換えは、個人の端末だけで完結しません。 GitHub のドキュメントや git-filter-repo のマニュアルでも、次の点が繰り返し注意されています。
  • 再汚染のリスク:古いクローンから git pull && git push されると、汚染履歴が戻る
  • 強制プッシュが必要になり、ブランチ保護が邪魔になることがある
  • 既存のクローンは原則 再クローン(または慎重なクリーンアップ)が必要

再発防止(仕組みで防ぐ)

シークレットを「コードから分離」する

  • 環境変数で注入する
  • Secrets Manager / Vault / Key Vault 等で管理する

.gitignore で入れ物ごと除外する

たとえば .env やローカル用の認証ファイルは、最初から追跡対象にしないようにします。

コミット前に止める(ローカルフック / CI)

  • git-secrets:コミット時にパターン一致を検出して拒否(Gitフックをインストールして運用)
  • gitleaks:リポジトリやディレクトリをスキャンしてシークレットを検出(pre-commit / GitHub Action などにも対応)

GitHub の secret scanning / push protection を使う

  • secret scanning:既知のシークレット形式を検出し、アラートで気づけるようにする
  • push protection:プッシュ中にスキャンして、検出したらプッシュをブロックする(事後ではなく事前に止められる)

CTF で安全に学ぶ(手を動かして定着させる)

「Git の履歴って、どこまで見られるの?」がピンと来ないときは、CTF みたいな安全な演習環境で一回だけ体験すると腹落ちしやすいです。 (実サービスや仕事のリポジトリで試すのはさすがに危ないので…)

たとえば Git の履歴は、ざっくり次の流れで辿れます。

  • ls -a.git があるか確認(配布物やディレクトリが Git リポジトリか分かる)
  • git log / git log --oneline で「何が起きたか」をまず眺める(コミットメッセージがヒントになることも)
  • git show <コミット> で「その時点の差分/ファイル内容」を見る(消したはずの内容が見えることがある)
  • さらに深掘りするなら git reflog、最悪でも .git/logs/HEAD を直接読む、みたいな手もある

公式(picoCTF / picoGym)はこちら:


このあたりを“軽く”体験できる記事を2本置いてます。気になった方だけどうぞ:


まとめ

  • Git は履歴を保持する仕組みなので、機密情報を一度コミットすると「削除したつもり」でも履歴に残り得ます。
  • 事故が起きたら、まず 失効/ローテーション。履歴書き換えは副作用が大きいので、必要性と影響範囲を見極めます。
  • 予防が最強です。.gitignore・フック・CI スキャン・GitHub の push protection などで「そもそも入れない」を徹底します。

参考文献