アクセスキー漏えいの初動|Gitにpush・チャットに貼ったときの順番
秘密情報を漏らしたと気づいたら、消すより先に止めます。無効化から再発防止までの順番と、報告の文面例を説明します。
.env をうっかりコミットした、ログを貼ったらトークンが写っていた、手順書に本番のパスワードを書いたまま共有した。秘密情報の漏えいは、操作 1 回で誰にでも起こります。気づいた直後は「早く消さなきゃ」と考えがちですが、ベテランが最初に手を付けるのは削除ではありません。漏れた認証情報を使えなくすることです。この記事では、気づいてから再発防止までの順番と、その順番になる理由を説明します。
「消せば大丈夫」が誤りである理由
認証情報は、文字列を知っている人なら誰でも使えます。一度どこかに出た文字列は、元の場所から消しても、すでに読んだ人や保存した仕組みの手元に残ります。公開リポジトリは第三者のツールによって常に走査されており、push から短時間で悪用されることがあります。よくある思い込みと、それが通らない理由を整理します。
| 思い込み | 実際に起きていること |
|---|---|
| コミットを消したから大丈夫 | push 済みなら、他の人のクローンや CI のキャッシュに残っている。消しただけではキーは有効なまま |
| force push で履歴を書き換えたから大丈夫 | GitHub ではフォーク、プルリクエストの参照、コミットの SHA を指定した表示から見えることがある |
| private リポジトリだから大丈夫 | 閲覧権限のある全員と、連携した外部サービスに渡っている。将来の公開や権限の付け間違いでも広がる |
| チャットの投稿を削除したから大丈夫 | 参加者の通知、端末、検索インデックス、エクスポートに残った可能性がある |
| 数分で気づいたから大丈夫 | 使われていないことは確認するまで分からない。時間の短さは無効化しない理由にならない |
GitHub の公式ドキュメントも、秘密情報を消す前の最初の手順として、その認証情報の無効化やローテーションを求めています。無効化が済めば、その文字列ではもうアクセスできません。履歴からの削除は、その後に必要かどうかを判断する作業です。
初動の順番は「止める・知らせる・調べる・消す・防ぐ」
- 止める:漏れた認証情報を無効化し、必要なら新しいものを発行して差し替える。
- 知らせる:上長やセキュリティの担当者に、隠さずすぐ報告する。
- 調べる:監査ログ、請求、不審なリソースから、使われた形跡がないかを確かめる。
- 消す:リポジトリやチャットから秘密情報を取り除く。
- 防ぐ:同じ漏えいが起きない仕組みを入れる。
止めることと知らせることは、ほぼ同時に進めてかまいません。自分に無効化の権限がない場合や、本番のアプリが使っているキーで止めると障害になる場合は、先に報告して判断を仰ぎます。迷っているあいだもキーは有効なままなので、一人で抱え込まないことが一番の近道です。
1. 漏れた認証情報をすぐ無効化する
AWS の IAM ユーザーのアクセスキーは、まず状態を Inactive にします。無効にしたキーは後から有効に戻せるので、影響を確かめてから削除できます。本番で使っているキーなら、新しいキーを発行してアプリの設定を差し替え、古いキーを無効にする順で進めます。AWS が公開されたキーを検知して通知を送ってくることもありますが、それを待つ必要はありません。
aws iam list-access-keys --user-name dev-tanakaaws iam update-access-key --user-name dev-tanaka --access-key-id AKIAEXAMPLE123 --status Inactive# 影響が無いことを確かめてから削除するaws iam delete-access-key --user-name dev-tanaka --access-key-id AKIAEXAMPLE123ほかの認証情報も考え方は同じです。GitHub の個人用アクセストークンは設定画面から削除し、外部サービスの API キーは管理画面で再発行します。DB のパスワードは変更し、そのパスワードを使っているアプリの設定も更新します。同じパスワードを別のシステムで使い回しているなら、そちらも変える必要があります。
2. 隠さず、早く報告する
漏えいを報告するのは気が重いものです。しかし、報告が遅れるほど調べる範囲が広がり、悪用されていた場合の被害も大きくなります。周りの人は責めるためではなく、止める権限や調べる手段を持っているから知らせてほしいのです。報告には、何が、どこに、いつから出ていて、今どこまで対応したかを書きます。
【報告】検証用 AWS アクセスキーを公開リポジトリに push しました・対象:IAM ユーザー dev-tanaka のアクセスキー(ID 末尾 E123)・場所:github.com/example/sample-app の main ブランチ、.env ファイル・期間:10/17 10:05 に push、10:40 に気づきました・対応済み:10:45 にキーを無効化しました。本番では使っていないキーです・これから:CloudTrail でこのキーの操作を確認します。履歴の削除はまだです・相談:他のリージョンの確認と、履歴削除の要否を相談させてください報告にキーの値そのものを書くと、漏えいの範囲を自分で広げてしまいます。アクセスキー ID の末尾や、ユーザー名、ファイルの場所で特定できるようにします。分かっていないことは「未確認」と書き、推測で「使われていません」と言い切らないようにします。
3. 使われた形跡がないかを確かめる
AWS では、CloudTrail のイベント履歴で、過去 90 日分の管理イベントを追加の設定なしで見られます。属性にアクセスキー ID を指定すると、そのキーで行われた操作だけに絞り込めます。イベント履歴はリージョンごとなので、普段使わないリージョンも含めて確認します。攻撃者は目立たないリージョンでインスタンスを起動することがあるためです。
aws cloudtrail lookup-events --region ap-northeast-1 --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAEXAMPLE123aws cloudtrail lookup-events --region us-east-1 --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAEXAMPLE123CreateUserやCreateAccessKeyなど、別の認証情報を作る操作がないか。IAM のようなグローバルサービスの操作はus-east-1のイベント履歴に記録される。作られていれば、それも無効化する。GetSessionTokenやAssumeRoleで一時的な認証情報が作られていないか。一時的な認証情報は元のキーを無効にしても期限まで使えるため、作られていれば拒否ポリシーの付与やセッションの取り消しを担当者と相談する。RunInstancesなど、身に覚えのないリソースを作る操作がないか。- 請求ダッシュボードで、普段と違うサービスやリージョンの料金が出ていないか。
- S3 の読み取りなどのデータイベントは既定では記録されないため、記録がないことを「使われていない」と読まない。
Google Cloud では Cloud Audit Logs、Azure ではアクティビティ ログが同じ役割を持ちます。不審なリソースは、何が作られたかを記録で把握してから止めます。調べる前に手当たり次第に削除すると、被害の範囲が分からなくなります。
4. 履歴やチャットから取り除く
無効化が済んだら、秘密情報を残しておかないために取り除きます。push 前に気づいたなら、コミットをやり直すだけで済みます。push 後に Git の履歴から消す場合は、GitHub のドキュメントが git-filter-repo を使う手順を案内しています。履歴を書き換えるとコミットのハッシュが変わり、共同作業者は古いクローンを捨てて取り直す必要があります。古いクローンから push されると、秘密情報が戻ってくるためです。
GitHub 上のキャッシュされた表示やプルリクエストの参照は、GitHub Support に削除を依頼できます。ただし、認証情報の無効化でリスクを抑えられる場合は対応しない、と GitHub は案内しています。フォークに残ったものは、フォークの持ち主に依頼するしかありません。チャットに貼った場合は、投稿を削除してもらい、同じ情報を転記したメモやチケットがないかも確認します。どの作業も「漏れた事実」を消すものではないことを、改めて意識してください。
5. 同じ漏えいを仕組みで防ぐ
再発防止は「次から気をつける」ではなく、間違えても止まる仕組みで考えます。まず .env や鍵のファイルを .gitignore に書き、値を抜いた .env.example だけをリポジトリに置きます。次に、コミットの前に秘密情報を検知するツールを入れます。AWS Labs の git-secrets や gitleaks は、コミット時にキーらしい文字列を見つけて止められます。
git secrets --installgit secrets --register-awsgit secrets --scan-historyGitHub の push protection は、push に含まれた秘密情報を検知して push 自体を止めます。個人アカウント向けの push protection は既定で有効で、公開リポジトリへの push を対象にしています。リポジトリ単位の push protection は GitHub Secret Protection が必要で、既定では無効なので、管理者に有効化を相談します。
最も確実なのは、漏れる長期のキーをそもそも持たないことです。クラウドの各サービスには、鍵を保存せずに短期の認証情報を受け取る仕組みがあります。
| 動かす場所 | 長期キーの代わりに使うもの |
|---|---|
| AWS の EC2・Lambda など | IAM ロールを付与し、一時的な認証情報を自動で受け取る |
| GitHub Actions などの CI | OIDC で短期の認証情報に交換する(Google Cloud では Workload Identity 連携、AWS では IAM ロールの引き受け) |
| Google Cloud の VM・Cloud Run | 必要なロールだけを持つサービスアカウントを関連付ける |
| Azure の App Service・VM | マネージド ID を有効にし、必要なロールを割り当てる |
秘密情報の漏えいは、隠したり消したりで終わらせようとすると被害が広がり、止めて知らせれば多くの場合は小さく収まります。下の問題で、漏えいに気づいたときの順番を確かめてみてください。
問題で確かめる
この記事の内容を、制限時間つきの問題で確かめられます。
参考
- AWS IAM User Guide: Manage access keys for IAM users
- AWS CloudTrail User Guide: Working with CloudTrail event history
- AWS IAM User Guide: Disabling permissions for temporary security credentials
- GitHub Docs: Removing sensitive data from a repository
- GitHub Docs: Push protection
- Google Cloud: Workload Identity Federation
- Microsoft Learn: What are managed identities for Azure resources?