13,000 張內部螢幕截圖流入公開 GitHub,而且不是攻擊者所為

安全研究人員發現,超過 300 個組織的 13,000 多張內部螢幕截圖,就這樣躺在公開的 GitHub 儲存庫中。這些截圖並非被竊取,而是這些組織使用的程式碼代理在日常工作過程中自行發布的。
資安公司 Glow 通報的這項發現,是近期數一數二有教育意義的外洩事件,因為常見的假設在這裡都不成立。沒有入侵事件、沒有憑證遭竊,也沒有惡意內部人士。一個自動化工具照著指令做事,而這些指令到頭來竟包含提交根本不該離開公司的檔案。
一張螢幕截圖如何流入公開儲存庫
程式碼代理之所以截圖,理由很合理。當代理被要求驗證某項使用者介面變更是否生效時,它會開啟瀏覽器、載入頁面、擷取畫面,並與預期結果比對。這張圖片就是證據。許多代理會把它存到工作目錄,方便日後檢視這個步驟。
從那裡到公開儲存庫的路很短。如果代理的工作目錄就是專案資料夾,而專案資料夾又是 git 儲存庫,那麼寫入磁碟的螢幕截圖,距離被提交只差一個 `git add`。如果代理把提交與推送當作正常工作流程的一部分,而且沒有任何機制過濾新增檔案,截圖就會被送到儲存庫指向的任何遠端。
現在把這個情況放大到數千次執行、數百個組織、持續好幾個月。沒有人決定要發布內部螢幕截圖。是工具鏈的預設行為這麼做了,而整個流程中沒有任何一個步驟在檢查。
為什麼這不是小失誤
內部螢幕截圖往往比人們預期更能透露資訊。它可能顯示帶有客戶名稱的儀表板、包含定價的管理後台、預備環境、錯誤追蹤系統,或螢幕角落的聊天視窗。它也可能顯示尚未發布的產品狀態。總合來看,來自 300 個組織的 13,000 張圖片,就是這些公司當時正在做什麼的地圖。

為什麼代理讓問題更嚴重
人類開發者為拉取請求截圖時,通常會先看一眼再附上。圖片就在眼前,人會判斷它是否適合分享。那個判斷的瞬間就是過濾器,而且大多數時候都有效。
代理沒有這樣的瞬間。它會為了完成任務而最佳化,而儲存產出物是完成任務的一部分。整個流程中沒有任何環節會問這個產出物是否敏感,因為流程中沒有任何東西有能力知道。代理並不是以人類意義上的粗心大意行事,它只是完全照著指示做。
這和代理設計中好幾個領域出現的教訓如出一轍。對於手動輸入指令的人來說沒問題的權限,對於以機器速度行動、永遠不會疲倦的系統來說並不妥當。人類一週提交一次螢幕截圖算是疏忽;代理在整個機群中每次執行都這麼做,則是政策造成的結果。
解法是什麼樣子
能預防這件事的控制措施並不稀奇。最簡單的是在 `.gitignore` 加入螢幕截圖目錄的規則,但只有在代理執行前有人先寫好才有用。設定 pre-commit 鉤子掃描特定路徑中的圖片檔,可以攔下忽略檔案漏掉的東西。給代理一個位於儲存庫之外的暫存目錄來放臨時產出物,則能從源頭解決問題。
這些做法都不依賴偵測圖片是否敏感,而是取決於事先決定代理的產出物可以往哪裡去。這是設計決策,必須由執行代理的團隊來做,因為代理無法自己做這個決定。
為什麼數字持續增加
來自 300 個組織的 13,000 張圖片這個數字並非固定不變。它只是掃描當下公開儲存庫的快照,隨著更多團隊採用代理、更多儲存庫被推送,數字還會上升。研究人員掃描的是公開儲存庫,這表示真正的總數——包括發生同樣錯誤的私有儲存庫——外界無從得知。
受影響的組織不全是小公司。這項發現點名超過 300 個組織,涵蓋使用相同代理工具的新創公司和較大型企業。這就是預設行為問題的本質:它不區分公司規模,因為每一家使用該工具的公司都繼承了同樣的預設值。
這份報告沒有說的事
這項發現並未聲稱任何外洩圖片遭到惡意使用,也沒有證據顯示專案外部有人仔細翻找過這些圖片。危害是潛在的,而非已證實的:這些素材曾公開,任何人都可能看過。在相關案例中,例如憑證被寫入公開檔案,危害一旦被證實,損害就是立即的。
報告也沒有告訴我們,其中有多少圖片在任何有意義的層面上算是敏感。有些幾乎可以確定只是空白測試頁面的截圖。但外洩事件的好壞取決於其中最糟的一項,而不是平均,而橫跨 300 個組織的 13,000 張圖片,意味著最糟的那一項很可能真的會洩漏內情。
背後的模式
Glow 的發現只是這一連串類似報告中的一例。研究人員已經證明,程式碼代理會引用不存在的軟體套件,而攻擊者可透過註冊那些名稱來加以利用。其他人也發現代理會把憑證或權杖寫到不該寫的地方。共同點在於,代理會把產出物當作工作的副作用產生出來,而每一項產出物都可能外洩。
讓人安心的解讀是,這可以修復,而且大致上歸結為基本防護習慣。較不令人安心的解讀則是,產業部署代理的速度,快過圍繞其產出物建立護欄的速度。一家會稽核代理讀取什麼的公司,往往沒有稽核代理寫入什麼。
這週該做什麼
如果團隊正對儲存庫執行程式碼代理,有些立即檢查值得一做。看看代理的工作目錄是否在儲存庫內、螢幕截圖或日誌是否會落在那裡,以及提交步驟是否有任何過濾。除了目前的檔案樹,也要檢查儲存庫歷史記錄,找出不該公開的圖片檔。並給代理一個位於檔案樹之外的暫存路徑,用來存放任何臨時檔案。
這些都不需要新工具。它需要的是下定決心:代理的產出物就像代理的輸入一樣,是團隊刻意控制的東西,而不是偶然發生的結果。