AI agent 的沙箱沒壞,權限例外卻可能把資料送出去
小團隊請 coding agent 檢查前端專案,順手確認測試服務還活著。為了讓它完成任務,負責人替沙箱開了一條規則:只准向指定服務發出 GET /health。這聽起來很節制。可是 GET 請求除了路徑,還有網址參數和標頭;如果規則沒有管到那裡,「只准讀健康狀態」就不等於「請求不會帶走其他資料」。
這是示意情境,不是我遇過的事故。它提醒我,一個沙箱最值得檢查的時候,往往不是剛裝好、什麼都不准做的時候,而是我們為了讓工作繼續,第一次替它開例外的時候。
預設拒絕,和例外安全,是兩件事
NVIDIA 把 OpenShell 定位為在 agent 工作負載外執行操作員政策的沙箱:檔案、網路、工具和憑證能由規則限制。這比請模型「記得不要碰祕密」可靠得多,因為限制不靠模型自律。另有可選的 Sentry 硬體參考設計;不能因為讀到 Sentry,就當作手上的 OpenShell 環境已經具備那層防護。
一份針對 OpenShell v0.1.2 的測試,在 Apple Silicon 主機的 microVM 環境裡,觀察到受測的預設拒絕政策擋住了嘗試的資料外送路徑;測試也沒有發現已記錄控制的繞過。這是好消息,但結論只到那組版本、設定與測試為止。操作員把出口打開後,問題變成另一個:目前寫下的規則究竟允許資料怎麼走?
在那份測試中,設定為阻擋的 L7 規則能擋下不被允許的 POST;但允許的 GET 請求,仍可能透過網址參數或 User-Agent 標頭帶出測試用的 canary。這不是沙箱被攻破,而是規則留下了可承載資料的出口。資料要真的送出去,還得有可達的目的地、可用的規則,以及 agent 能接觸到的資料;也不能因此說每個 GET 都會外洩。
測試裡另一個容易看錯的地方是 L7 規則的執行模式:在受測設定下,沒有明確設為 enforcement: enforce 的規則處於 audit,違規請求留下紀錄,卻不會被它擋住。看到日誌有事件,不代表限制已生效。這也不表示整個沙箱預設允許對外連線;要核對的是那一條規則實際採用的模式。
替權限例外留一個會失敗的測試
如果是我替那個測試服務開放出口,會把政策變更當成程式碼變更來審:這次任務究竟要讀哪些檔案?目的地是否限於團隊控制的服務?允許的方法與路徑之外,網址參數和標頭有沒有必要全數帶出?規則是阻擋,還是只記錄?自動核准是否也被打開?先寫清楚核准理由,再看政策差異,而不是只看 agent 終於能不能完成任務。
驗收時,我會在不含真實憑證的隔離環境放一個無效測試值,先列出本應被拒絕的目的地或請求,再確認這些請求真的被阻擋。對新開的 GET /health,也要檢查不該出現的資料能否透過參數或標頭離開;若業務確實需要參數,就把允許的內容與範圍寫得更窄。記錄變更前後的規則、核准人、實際請求結果與日誌的 audit/enforce 狀態,日後才有辦法查出邊界從哪次修改開始改變。這是我建議的驗收方式,不是已替任何部署跑過的檢查。
有些政策驗證工具會對特定規則回報 unsupported 或 inconclusive。這種結果要留給人工檢查,不能填成「安全測試通過」。canary 通過也只表示這次設計的測試路徑符合預期,不能保證沒有其他出口,更不會替你判斷 agent 寫的程式碼是否正確。
沙箱能幫我們執行邊界,卻不能替我們決定例外該開多大。下次替 agent 增加權限,除了確認它現在做得到什麼,也留一筆證據:原本不該出去的東西,現在是否仍然出不去。