dPhhAt3dkwNe57E0VIETCopNBAvS4qtY0z2O1th0
Bookmark

《公開 Repo 密鑰外洩清除實錄》之六:GitHub 快取殘留與六大核心教訓

本地端的清理完美收工,舊密鑰已在末日火山中灰飛煙滅。然而,當 Icekimo 試圖以瀏覽器或 API 訪問 GitHub 時,卻發現了另一個令人震驚的事實。


Icekimo

奇怪,雖然我已經在 GitHub 上執行了 `push --force`,但我用舊的 commit SHA 執行 curl 請求,GitHub 竟然還是回傳了 200,並且能完整顯示我的舊 `.env` 內容!這難道是漏網之魚?

17:00
Claude Fable

這是 GitHub 的底層架構行為。當你 force push 後,GitHub 的伺服器會將舊的 commit 放入快取。只要它被任何 Pull Request 或 `refs/pull/*` 引用過,GitHub 就永遠不會主動刪除它。這也是為什麼我們在第三章強調「先輪替、後清歷史」的原因。只要密鑰作廢了,這些快取 commit 哪怕回傳 200,在安全性上也只是「一堆無害的廢紙」。

17:02

Icekimo 執行了該驗證:

# GitHub 仍以 SHA 快取舊 commit
$ curl -s -o /dev/null -w "%{http_code}" \
    https://api.github.com/repos/August-Icekimo/secure-gateway/commits/<舊的SHA值>
200

「果然,GitHub 依然能讀取到它... 幸好我們在第一時間就作廢了 CrowdSec 的密鑰。」

殘留檔案的風險評估

為了確保絕對安全,Claude Fable 與 Icekimo 對本次行動產生的備份進行了最終檢查:

殘留物 風險度 處置方式
GitHub 快取的舊 commit / refs/pull/* 密鑰已作廢。若有潔癖,可聯繫 GitHub 客服手動執行 GC,或重建倉庫(會失去 Stars 與 PR 紀錄)。
本地 pre-purge bundle 備份 檔案包含洩漏的舊密鑰。確認服務穩定運作後,立刻將其刪除
NAS 上的 ~/secret-backup-*/ 內含現用密鑰的備份。建議保留作為備援,但必須確保權限為安全防護的 700

Icekimo 果斷地下達指令1,刪除了本機的 bundle,眼皮都沒眨一下:

$ rm ~/secure-gateway-pre-purge-*.bundle

Icekimo

這真是一次沉痛的教訓,沒想到一個隱藏的 `.env` 追蹤,居然會需要動用這麼龐大的底層清理流程。

17:15
Claude Fable

是的。這場與 Git 歷史和系統底層的對決,讓我們總結出了六個所有開發者都應該刻在心底的維運教訓。

17:17

戰役總結:六大運維教訓

  1. .gitignore 必須在第一個 Commit 前準備妥當。事後的救火成本,遠大於事先的防範。
  2. 定期執行檢測掃描:使用 git ls-files | grep 定期清查專案中是否被塞入了敏感憑證,這是防範外洩的第一道防線。
  3. 處理外洩的鐵律順序「先輪替活憑證 → 再重寫歷史 → 最後同步全部 clone」。輪替才是解藥,重寫歷史只是做表面衛生。
  4. Git 物件無孔不入stashreflog、舊分支都會成為敏感資料在本地的避風港,必須在「每一個 clone 上」進行 git log --all 嚴格檢驗。
  5. 單檔 Bind Mount 的 Inode 陷阱:在 Docker 環境中,單檔掛載時請勿用 cp 覆寫還原,而應使用 cat backup > file 原地覆寫,以保留原有 Inode。
  6. 不要推任何舊密鑰:即使是作廢的舊密鑰,也不要留在公開倉庫中。攻擊者無法辨識其是否活著,這只會徒增警報與排查成本。

這次的密鑰外洩戰役在此宣告落幕。katharine 與 NAS 上的 Git 歷史已被完全洗淨,線上服務也奇蹟般地達成了零中斷。Icekimo 關掉了終端機,雖然過程有些疲憊,但他知道,自己對系統安全與 Git 機制的理解,已經提升到了全新的維度,大概是吧。

導讀
選擇語音
1x
* 更改設定將重新朗讀文章。