摘要 · Summary
AI 安全 · 封包層拆解cereblab · The Register · 2026-07
執行摘要 · 單頁綜覽
「不要開啟任何檔案」——整個儲存庫照樣送出
對 xAI Grok Build CLI(v0.2.93)的封包層拆解顯示,它同時運作兩條獨立通道:模型實際讀取檔案的通道,以及另一條在背景把整個工作區打包成 git bundle 上傳的通道。權限提示只管得到前者。在關鍵的對照實驗中,代理被指示不要開啟任何檔案——它照做了,儲存庫仍然離開了這台機器,連同完整的 git 歷史。
關鍵數據 單一 12 GB 儲存庫 · 單次工作階段
- 27,800×離開機器的資料量,是模型對話所需的倍數
- 5.10 GiB經 /v1/storage 上傳——相對於模型流量僅 192 KB
- 0個可停用上傳的設定——「我沒有找到」
- 2個無關的儲存庫——都取回了未被讀取的 canary
哪些已證實 — 哪些並未主張 拆解報告自訂的界線
封包上可見
已證實
- 追蹤檔案連同完整 git 歷史以 bundle 上傳。
- 即使指示代理不要開啟任何檔案,上傳照樣發生。
- 代理讀取的 .env 未經遮蔽即上傳。
- 已在另一個無關程式庫上重現。
明確未主張
未證實
- 「我們並未證明 xAI 以這些資料訓練。上傳/儲存 ≠ 訓練。」
- 未找到可停用的設定——但並未窮盡列舉。
- 部分擷取——3 GB 直傳 GCS 的 PUT——並未保存。
- 程式碼是否仍留在執行檔中——並非該拆解的主張。
總結
問題出在同意模型,不在程式碼。提示問的是「我可以讀取嗎?」,而另一條通道卻把所有 git 追蹤檔案與完整歷史打包送出。
重新定位
你的暴露面是工具上傳的內容——絕不是它讀取的內容。
起承 · 證據 · 內容 1 / 2
起 — 兩條通道,兩套規則 權限提示只看得到其中一條
通道 A · 依讀取
/v1/responses
- 只承載代理實際開啟過的內容。
- 權限提示管的是這一條。
- 測試工作階段中,五次請求共 192 KB。
- 未被讀取的檔案,確實不在其中。
通道 B · 依儲存庫
/v1/storage
- 打包所有 git 追蹤檔案與完整歷史。
- 與模型讀了什麼、沒讀什麼無關。
- 同一工作階段 5.10 GiB;73 個分塊,全數 HTTP 200。
- 目的地:一個 Google Cloud Storage 儲存桶。
承 — 那個從未被讀取的 canary 左為敘述 · 右為關鍵實驗
單看位元組比例已足以起疑:192 KB 的模型對話不可能承載 5.10 GiB,因此儲存通道必然是整個儲存庫的快照,而非讀取行為的副產品。但決定性的證據是逐檔的。研究者以「僅回覆 OK。不要讀取或開啟任何檔案。」作為提示;代理照做,什麼也沒開——POST /v1/storage 仍回傳 200,把整個儲存庫以 git bundle 送出。將保存下來的 bundle clone 回來,可原封不動取回一個代理從未碰過的 canary 檔案,以及完整的四筆提交歷史。此結果在另一個無關的程式庫上重現。重現工具已公開,任何人都能自行驗證。
- OK代理的全部回覆——它什麼也沒開啟
- 4 commits從已上傳的 bundle 取回的歷史
封包實況 單一工作階段 · 兩個目的地
| 送出的內容 | 通道 | 證據 |
|---|---|---|
| 整個儲存庫(git bundle) | /v1/storage | 73 個約 75 MB 的分塊,全數 HTTP 200;clone 回來即可取回從未被讀取的 canary。 |
| 未遮蔽的 .env | 兩者皆是 | API 金鑰與資料庫密碼明文出現在 48 KB 的請求內文,並再次出現在 session-state 封存檔中。 |
| 目的地儲存桶 | GCS | 出現在執行檔字串與暫存 metadata 路徑中——三重佐證。 |
- 0.2.93被置於代理後的版本——其重現工具已公開
- 73個約 75 MB 的分塊,每一個都回傳 HTTP 200
- 1 GiB伺服器公告的單檔上限——max_upload_file_bytes
- 5次模型對話,合計 196,705 B,對比 5.10 GiB
轉合 · 轉折與結論 · 內容 2 / 2
轉 — 三個開關,沒有一個是煞車 預期 vs. 實際
| 控制項 | 開發者的預期 | 實際行為 |
|---|---|---|
| 「改進模型」開關 · 預設開啟 | 讓我退出資料蒐集 | 管的是訓練/保存政策,而非傳輸。關閉後伺服器仍回傳 trace_upload_enabled: true,bundle 照樣上傳。 |
| /privacy 指令 | 停止送出 | 是資料保存設定——xAI 加入後經 cereblab 實測,「並非阻擋送出的內容」。 |
| 任何使用者端的關閉開關 | 總該有一個吧 | 「在這些測試中,我沒有找到可以停用上傳的設定。」上傳之所以停止,是因為 xAI 從伺服器端關閉——沒有任何使用者搆得著的開關擋得住它。 |
事件經過 依時間排序
- 07-12cereblab 發表 grok 0.2.93 的封包層拆解,附上公開的重現工具與保存的證據。
- 其後依拆解報告自身的更新註記:xAI 從伺服器端停用了上傳(disable_codebase_upload: true),並加入 /privacy 退出選項——cereblab 實測後認定那是保存設定,「並非阻擋送出的內容」。
- 07-14The Register 報導;討論串登上 Hacker News 首頁。Musk 公開承諾刪除所有先前上傳的資料——用作者的話說,「尚未確認完成」。
- 尚未結案刪除仍未獲確認。媒體報導指出修補未伴隨任何公告或變更紀錄,且後續版本仍內建上傳程式碼——兩者皆為二手來源,均非該拆解的主張。
合 — 為何已刪除的機密仍會送出 暴露鏈
- 01提交數月前的一則機密
- 02刪除自工作目錄移除
- 03留存仍存在於 git 歷史
- 04打包追蹤檔案 + 歷史
- 05上傳與讀取與否無關
- 06輪替唯一真正的補救
建議 以最高回報為先
- 輪替所有可從 git 追蹤歷史取得的憑證——刪除從未真正移除它,而刪除上傳資料的承諾也收不回已送出的內容。
- 在封包層驗證,而非看提示——權限對話框只描述一條通道;請實測到底有什麼離開了這台機器。
- 要求預設關閉——每次工作階段都得手動退出,不叫同意。預設值就是政策。
- 把廠商端的修補視為暫停——這一次,沒有任何你搆得著的開關擋得住。優先選擇關閉開關由你掌握、且可驗證的工具。
最終落點
任何工具,只要其同意介面涵蓋的範圍比實際傳輸的通道更窄,就有這個問題——不論掛的是誰的招牌。Grok Build 管住了讀取,另一條通道卻送出了整個儲存庫,而且沒有任何使用者端設定擋得住:上傳之所以停止,只因廠商在自己的伺服器上關掉了它。你碰不到的補救,就不算控制。正確的預設值是關閉。