🚨
APIキー漏洩インシデント対応記録 - 個人開発で学んだセキュリティの重要性
はじめに
個人開発でFlutterアプリを作成中、GCP(Google Cloud Platform)からAPIキー漏洩の通知メールが届きました。この記事では、実際に発生したインシデントの対応過程を時系列で整理し、学んだ教訓と再発防止策をまとめています。
同じような経験をされた方や、これから開発を始める方の参考になれば幸いです。
インシデント概要
基本情報
- 発生日時: 2025年11月4日 11:00頃
- 発見方法: GCPからのAPIキー漏洩通知メール
- 影響範囲: 個人開発プロジェクト(ステークホルダー:開発者1名のみ)
- プロジェクト: Flutterによるモバイルアプリケーション
- 関係者: 開発者1名(筆者)
漏洩内容
-
対象ファイル:
lib/firebase_options.dart - 該当ブランチ: 認証機能実装用のfeatureブランチ
- 該当コミット: [コミットハッシュ非公開]
- 漏洩情報: Firebase APIキー、プロジェクトID等の機密情報
タイムライン
2025年11月2日頃
- Firebase認証機能の実装
- APIキーをソースコードにハードコーディング
- GitHubパブリックリポジトリにプッシュ
2025年11月4日 11:00
- インシデント発覚: GCPからAPIキー漏洩の通知メール受信
- Googlebotによるクロールで発見されたと推測
2025年11月4日 11:30-12:00
-
初動対応
- リポジトリの非公開化を実施
- 影響範囲の調査開始
2025年11月4日 12:00-14:00
-
影響調査
- 汚染ブランチの特定:本番環境、開発環境、および複数のfeatureブランチ
- 機密情報が含まれるファイルの全体調査
2025年11月4日 14:00-16:00
-
対応方針の検討
- 案1: リポジトリ再構築
- 案2: git rebaseによる履歴修正
- 最終決定: git-filter-repoによる履歴完全削除
2025年11月4日 16:00-18:00
-
復旧作業
- git-filter-repoによる機密情報削除
- GCPコンソールでAPIキーローテーション実施
- 環境変数による設定管理への変更
原因調査
根本原因
-
開発プロセスの問題
- AIアシスタントが生成したコードをそのまま使用
- 機密情報のハードコーディングに対する認識不足
- コードレビューの不実施(個人開発のため)
-
技術的な問題
-
google-services.jsonファイルの存在を把握していなかった- このファイルは通常
.gitignoreに追加すべきだが、その認識が不足していた - Firebase設定時にFlutterfireが自動生成するファイルで、プロジェクトの機密情報が含まれる
- このファイルは通常
- Flutterfireツールが自動生成するファイルに機密情報が含まれることへの理解不足
-
発見までの経緯
- コミットから約2日後に通知メール受信
- Googlebotによる自動クロールが原因と推測
- パブリックリポジトリのため、検索エンジンにインデックスされていた可能性
実施した対処内容
即座の対応
-
リポジトリの非公開化
- GitHubリポジトリを即座にprivateに変更
-
APIキーのローテーション
- GCPコンソールで該当APIキーを無効化
- 新しいAPIキーを生成
根本対策
-
履歴の完全削除
# git-filter-repoを使用して機密情報を含むファイルを履歴から完全削除 git filter-repo --path lib/firebase_options.dart --invert-paths -
設定管理の改善
- 機密情報を環境変数で管理するように変更
- ローカル実行時は
--dart-defineオプションで機密情報を渡す方式に変更
flutter run --dart-define=API_KEY=your_api_key -
Firebase設定の見直し
-
google-services.jsonファイルの削除- 注意:通常はこのファイルを削除するのではなく
.gitignoreに追加して管理する - 今回は機密情報漏洩対応のため、環境変数による設定管理に完全移行
- 注意:通常はこのファイルを削除するのではなく
- Gradleプラグイン(
com.google.gms.google-services)の削除-
google-services.jsonを使用しない設定管理方式への変更に伴う対応
-
-
発生した不具合と解決
1. ローカルビルドエラー
問題: google-services.json削除によりFirebase関連のビルドが通らない
解決策:
- Firebase設定を環境変数から動的に読み込むDartコードに変更
-
--dart-defineオプションで実行時に機密情報を注入する方式に移行
// 従来: google-services.jsonから自動読み込み
// 変更後: 環境変数から動的設定
static const FirebaseOptions android = FirebaseOptions(
apiKey: String.fromEnvironment('FIREBASE_API_KEY'),
appId: String.fromEnvironment('FIREBASE_APP_ID'),
projectId: String.fromEnvironment('FIREBASE_PROJECT_ID'),
);
2. GitHub Actionsビルドエラー
問題: CI/CDパイプラインでの環境変数設定漏れ
解決策:
- GitHubリポジトリシークレットに機密情報を登録
- ワークフローファイルで環境変数を適切に設定
振り返り
良かった点
- 迅速な初動対応: メール受信から30分以内にリポジトリ非公開化
-
徹底した調査:
findコマンドで全ファイルを調査し、他の機密情報漏洩がないことを確認 - 根本的な解決: git-filter-repoによる完全な履歴削除
課題点
- 事前防止の不備: そもそも機密情報をコミットしてしまった
- AIツール依存: 生成されたコードの内容を十分に理解せずに使用
- 知識不足: Flutterfireが生成するファイルの内容を把握していなかった
改善点
- コミット前チェック: 機密情報が含まれていないかの確認を習慣化
- AIツール使用時の注意: 生成されたコードは必ず内容を確認してから使用
- 設定管理の統一: プロジェクト開始時に環境変数による設定管理を前提とする
再発防止のためのアクションプラン
1. 開発プロセスの改善
-
.envファイルのテンプレート作成 - pre-commitフックによる機密情報チェック
- 定期的なセキュリティ監査の実施
2. 技術的対策
# pre-commitフックの例
#!/bin/sh
# 機密情報パターンをチェック
if git diff --cached --name-only | xargs grep -l "api.*key\|secret\|password" 2>/dev/null; then
echo "ERROR: 機密情報が含まれている可能性があります"
exit 1
fi
3. 教育・啓発
- セキュリティベストプラクティスの学習
- AIツール使用時のガイドライン策定
- 定期的な脆弱性情報の収集
学んだ教訓
-
「AIが悪い」では済まない
- AIツールは便利だが、最終的な責任は開発者にある
- 生成されたコードは必ず内容を理解してから使用する
-
個人開発でもセキュリティは重要
- 規模が小さくても基本的なセキュリティ対策は必須
- 「後で直せばいい」という考えは危険
-
早期発見・迅速対応の重要性
- 監視・通知システムの効果を実感
- 初動対応の速さが被害拡大を防ぐ
おわりに
今回のインシデントは、個人開発においてもセキュリティ意識を持つことの重要性を改めて認識させられる出来事でした。
特に、AIツールが普及する現在において、生成されたコードをそのまま使用することのリスクを身をもって体験しました。便利なツールを使いこなすためには、それに対応した知識と注意が必要だということを学びました。
同じような経験をされた方、これから開発を始める方の参考になれば幸いです。セキュリティは「面倒なもの」ではなく、「開発の基盤」として捉え、日々の開発に組み込んでいきましょう。
Discussion