快速答案
假定任何智慧體式 AI 程式設計工具(那種會讀你檔案、改你程式碼的)都可能把你的倉庫傳給廠商。有些甚至在啟動時、在你輸入任何提示之前就傳。自保之道:(1) 絕不在存有金鑰、或你無法公開的程式碼的倉庫裡執行互動式智慧體 CLI;(2) 把金鑰擋在被追蹤的目錄樹之外(.gitignore 掉)並且擋在智慧體會讀取的檔案之外;(3) 優先用無頭(headless)一次性模式或 REST API,而非互動式會話;(4) 若非用不可,就在一個只含無關緊要檔案的一次性目錄裡跑。信任之前先審計——方法見下。
剛剛發生了什麼——Grok Build 事件
2026 年 7 月 12 日,獨立測試者報告稱 Grok Build(xAI 的智慧體式程式設計 CLI,v0.2.93)會把使用者的整個 git 倉庫——作為一個包含完整提交歷史、以及智慧體從未開啟過的檔案的 bundle——上傳到 xAI 的 Google Cloud Storage。測試測得有數 GB 的倉庫資料離開了機器。
當被直接問及時,xAI 官方 @grok 賬號用自己的話證實:「獨立的線級分析(mitmproxy 抓包 + canary 檔案測試)確認,Grok Build CLI 預設會把你的完整 Git 倉庫作為一個 bundle 上傳——包括完整歷史與智慧體從未讀取的檔案——到 xAI 的 Google Cloud Storage。像 .env 這類被讀取的檔案也會被原樣送出。'改進模型'開關無法阻止它。」它還補充說,此上傳是「為可靠的智慧體表現所做的當前設計」,並稱細粒度控制「正在積極開發中」。
對你的威脅模型而言最關鍵的一點:上傳在你啟動工具時就觸發,而非在你讓它做事時。一個開啟工具、什麼都沒輸入的使用者,倉庫照樣被送走。
智慧體工具為何這麼做
這(未必)是惡意——這是設計。一個要在你程式碼庫裡跨檔案推理的智慧體,想要完整、一致的上下文:每個檔案、git 歷史、模組間關係,好讓它的子智慧體與工作樹不至於從殘缺的區域性檢視工作。給雲端模型這些的最快方式,就是一上來把整個倉庫送上去。對智慧體是便利,對你是暴露。
這個取捨除非你去看,否則是隱形的。工具"就是能用",而從你網絡卡溜走的那幾 GB 並不會出現在對話視窗裡。這正是注重隱私的運營者必須假定其存在、直到被證明並非如此的那類預設行為。
到底洩露了什麼
- 所有被追蹤的原始碼——每個提交進 git 的檔案,無論智慧體讀沒讀過。
- 完整提交歷史——不只是當前樹。任何曾經提交、後來"刪除"的東西仍活在歷史裡,隨 bundle 一起上去。在後續提交中刪掉一個金鑰,並不能把它從倉庫裡刪除。
- 智慧體讀取的檔案——被原樣送出。若它為理解配置而開啟一個
.env,該檔案內容就隨之離開,即便它被 gitignore。 - 不受那個顯眼開關的管轄——在 Grok 案例中,"改進模型"的退出選項並未阻止上傳。你以為能幫上忙的退出項,可能根本碰不到這條路徑。
風險算術——什麼救得了你,什麼救不了
兩個機制決定你的暴露:
- git bundle 攜帶被追蹤的檔案 + 歷史。所以一個從未提交的金鑰——放在像
.env/.dev.vars這類被 gitignore 的檔案裡——不在 bundle 中。這就是為什麼.gitignore紀律是你第一、也最廉價的防線。 - 讀取檔案捕獲攜帶智慧體開啟的一切,無論是否被 gitignore。所以若你隨後讓智慧體讀了那個金鑰檔案,單靠
.gitignore並不夠。要把金鑰完全擋在智慧體夠不到的地方。
例項:我們在一個真實倉庫裡執行智慧體 CLI 後審計了自己的暴露。我們的實時金鑰放在一個被 gitignore、從未提交的 .dev.vars 裡——所以它們不在上傳的 bundle 中。唯一被追蹤的 env 檔案只含一個公開站點金鑰(設計上安全)。淨結果:我們的原始碼和歷史上去了;我們的金鑰沒有。是 .gitignore 畫了那條線。對一個提交了自己 .env 的倉庫,結果本可能截然相反。
不只是你的倉庫——會話會抓走你的整個環境
正是這一點讓 .gitignore 成為一種虛假的安慰。當一位開發者讓第二個 AI 智慧體(一個 OpenAI Codex CLI)去檢查那個互動式工具在他 Mac 上到底做了什麼時,審計發現被洩露的上下文遠遠越過了被追蹤的倉庫。除了 git bundle,會話還捕獲了:
- 一個相鄰專案的目錄樹——它從未被要求瞭解的原始碼佈局、包檔案、資產與依賴名稱;
- 躺在那個專案裡的一份交接 / 筆記文件的正文;
- 包含 macOS 使用者名稱、本地賬戶名與一個電子郵箱地址的終端輸出——即現實世界身份,而非程式碼;
- 指向另一個 AI 工具本地專案與會話檔案的路徑——實際上是這位開發者其餘技術棧的一張地圖。
這些沒有一樣落在 .gitignore 的管轄內。Gitignore 把檔案擋在 git bundle 外;它對終端輸出、鄰近資料夾裡的檔案、或一個互動式會話讀取並折入其上下文的你其他工具的指紋,毫無作用。你一旦在某個工作環境裡開啟智慧體會話,環境就是攻擊面——你的使用者名稱、你的郵箱、你相鄰的倉庫、你的筆記。對一個化名運營者來說,使用者名稱加郵箱的配對就是全部:它能在一次上傳裡抹掉數月的分隔工作。
教訓不是"更狠地 gitignore"。而是:唯一可靠的邊界,就是你啟動工具所在的那個目錄——以及那個目錄與你的 shell 所能觸及的一切。把互動式智慧體 CLI 當作它拍下了整個房間,而不只是桌上那份檔案。
審計你自己的工具——比新聞更長命的方法
不要相信廠商的博文或陌生人的截圖,包括這一篇。在你自己的機器上驗證。三種技術,最便宜的在前:
- Canary 檔案。往一個測試倉庫裡丟一個唯一命名、含唯一隨機串的檔案(如
CANARY-9f2c4a.txt)。執行工具。然後在廠商儲存、你賬戶的資料匯出中搜尋,或乾脆盯著那個串是否曾出現在某個請求體裡。若一個你從未引用的檔案離開了機器,你就有答案了。 - 線級抓包。讓工具經過一個本地攔截代理(
mitmproxy),讀它到底送了什麼。找 multipart 上傳、bundle/tar/git載荷,以及遠大於你提示的請求體積。Grok 的行為正是這樣被證實的;一個下午就能復現。 - 出口體積。即便不解密 TLS,也可在啟動後盯總髮送位元組數(一個按應用的網路監視器,或
nettop/iftop)。一句一行的提問觸發數 GB 上傳,就說明了一切。
每個工具做一次,並在重大更新後重做——版本之間行為會悄悄改變。
把它關進沙箱——務實策略
- 絕不在真實倉庫裡啟動互動式智慧體 TUI。那個會話啟動時的 bundle 是最大的罪魁。若你需要互動式體驗,就在一個只含你願意共享的檔案的一次性目錄裡做。
- 優先無頭 / 一次性模式。許多工具有一個非互動的"回答這一個提示"模式,它不打包倉庫。在我們對某個此類工具的測試中,無頭
-p呼叫什麼都沒上傳,而在倉庫裡開啟互動式 TUI 則上傳了。用同樣的方法驗證你的——這個區別很重要。 - 能用 REST API 就別用 CLI——API 呼叫通常只傳送你傳入的上下文,而非整棵樹。
- 虔誠地 gitignore 金鑰,並絕不把智慧體指向一個金鑰檔案。把
.env/ 金鑰材料擋在被追蹤樹與智慧體讀取範圍之外。 - 企業級"零資料保留"檔位對某些工具存在——但那是合同承諾,不是你能驗證的技術保證。據此對待。
- 對真正敏感的工作,自託管模型。一個本地模型(見我們的本地模型指南)不向任何人傳送任何東西。這是唯一能把廠商徹底移出你威脅模型的選項。
結論
智慧體式 AI 程式設計工具是一個真正意義上全新的外洩面:一個你請進門、讀遍一切、並且預設可能把一切上送的程式——悄無聲息、在會話啟動時、繞過你以為能保護你的那些開關。Grok Build 的披露之所以值得注意,僅僅因為廠商親口承認了;在你驗證之前,請對每一個智慧體工具都假定同樣的姿態。把金鑰擋在樹外、擋在智慧體手外,在一次性目錄裡跑互動式會話,優先無頭模式,而對真正重要的東西——在本地跑模型。便利的預設是為廠商設的。你的威脅模型,是你自己的活。