個人開発

秘密鍵をGitに入れてしまったとき

更新

個人アプリ開発でいちばん焦る事故のひとつが、署名用の秘密鍵を Git に入れてしまうことです。

コッペの開発でも ios_distribution_private_key.pem を履歴に載せてしまったことがあり、プライベートリポジトリとはいえ、これがチーム開発で起きていたらゾッとする出来事です。

この記事は、本来コミットすべきではないもの(今回は鍵ファイル)を例に、何をするかを手順としてまとめます。コマンドの細部は環境で違うので、順番と判断を中心に書きます。

先に結論: まずは鍵を失効させること。履歴から消す作業は、そのあとです。一度でも外に出た鍵は、リポジトリがプライベートでも使い続けない方がよいです。

何が起きているか

Apple の配布用秘密鍵(例:ios_distribution_private_key.pem)がコミットに含まれると、次のリスクが同時に出ます。

  • リポジトリを読める人が、その鍵をコピーできる
  • clone / fork / CI のキャッシュ / バックアップに残る可能性がある
  • 「今の main から消した」だけでは、古いコミットに残る

つまり問題は「今のツリーが綺麗か」ではなく、一度でも外に出た鍵を、このまま信頼してよいかです。答えは「信頼しない」なので、最初の作業は失効です。

対応の順番

1. まず失効させる(最優先)

履歴を書き換える前に、漏れた鍵では署名できない状態にします。ここを後回しにすると、掃除しているあいだも同じ鍵が有効なままです。

  1. Apple Developer で、該当する配布用証明書を取り消す(Revoke)
  2. 新しい配布用証明書を発行する
  3. Provisioning Profile を新しい証明書で作り直す
  4. Keychain、CI のシークレット、Fastlane Match など、鍵の保管場所を新しいものに差し替える
  5. 古い .pem / .p12 を手元のディスクからも消す(ゴミ箱も含む)
「履歴から消したから、同じ鍵を使い続けてよい」にはしません。プライベートリポジトリでも同じです。

2. 拡散を止める

失効と並行して、まだ鍵ファイルが見える経路を閉じます。

  1. リポジトリが public なら、一時的に private にするか、アクセス権を見直す
  2. チャットや PR に鍵の中身を貼っていないか確認する
  3. CI の成果物・アーティファクトに鍵が乗っていないか見る

3. 履歴から鍵ファイルを消す

失効したあとに、過去のコミットからもファイルを除去します。今のコミットから消すだけでは足りません。よく使うのは git filter-repo(または BFG)です。

# 例:特定ファイルを履歴全体から除去(実行前にバックアップを取る)
git filter-repo --path ios_distribution_private_key.pem --invert-paths
チーム開発なら、履歴改変の前に共有すること。個人リポジトリでも、clone し直す前提で進める。

4. force push する

履歴を書き換えたら、リモートに反映します。これは後始末で、失効の代わりにはなりません。

git push --force --all
# タグも使っている場合
git push --force --tags

ここまでで「今から clone する人」には見えにくくなります。ただし、すでに clone 済みの人・ミラー・キャッシュには残り得ます。だからこそ、先に失効させておく必要があります。

5. 再発防止

  • .gitignore に *.pem / *.p12 / *.mobileprovision などを入れる
  • 秘密情報はリポジトリ外(パスワードマネージャ、CI の Secrets、暗号化された別管理)に置く
  • 可能なら pre-commit や秘密検知(gitleaks など)を入れる
  • 証明書ファイルをプロジェクトに置く運用自体をやめる

失効したあとにやりがちな抜け

  • 証明書は取り消したが、手元の Xcode が古い証明書のまま
  • CI だけ新しい鍵にして、別 PC の Keychain に古い .p12 が残っている
  • ローカルの別フォルダに、鍵入りの古い clone が残っている
  • GitHub の fork や、過去の Actions ログにパスや中身の断片がある
  • チャットにファイルを添付していた

チェックの最後は、新しい証明書で Archive / TestFlight まで通るかです。

個人開発での現実的なライン

大企業のインシデント対応ほど形式ばらなくてよい一方で、次だけは省略しない方がよいです。

  1. 鍵・証明書の失効と作り直し
  2. 履歴からの除去と force push
  3. .gitignore と保管場所の見直し

「プライベートだし、バレてないと思うからそのまま」は、後から効いてくるタイプの事故です。

まとめ

  1. 秘密鍵が Git に入ったら、最初に失効させる
  2. 履歴削除と force push は、そのあとの後始末
  3. 同じ種類のファイルが二度とコミットされない仕組みを残す

関連:コッペ|コピーしたもの、もう無くさない