← All posts / Meta

在規則之內繞過規則:SGLang SafeUnpickler 旁路成為 18 天內第四個關鍵 AI 基礎設施 CVE

CVE-2026-86793 讓未經身分驗證的攻擊者只需串接兩個「被允許」的 Python 內建函式,就能在 SGLang 推論伺服器上執行任意程式碼,且官方修補至今尚未推出。這是 8 月 25 日以來第四個重創 AI 技術棧的關鍵 CVE。

在規則之內繞過規則:SGLang SafeUnpickler 旁路成為 18 天內第四個關鍵 AI 基礎設施 CVE

2026 年 9 月 11 日,資安廠商 VicOne 公開了 CVE-2026-86793 的完整技術分析。這個存在於 SGLang——目前最廣泛部署的開源大型語言模型推論框架之一——的漏洞,允許遠端、未經身分驗證的攻擊者在受害伺服器上執行任意程式碼。但這個漏洞真正令人注意的地方不只是嚴重性,而是旁路手法的優雅:攻擊者從頭到尾沒有違反 SGLang 的任何一條安全規則,只是乖乖地「在規則之內」使用它們。

一個專門為了防堵這類攻擊而生的防護

SGLang 並非第一次踩到這個坑。框架中的 SafeUnpickler 類別,正是為了修補先前的 CVE-2025-10164 而加入的——那是一個利用不安全 pickle 反序列化達成任意程式碼執行的漏洞。Pickle 是 Python 原生的序列化格式,也是機器學習生態系中惡名昭彰的攻擊面:當 pickle 位元組流被反序列化時,unpickler 可能會匯入模組、解析類別或函式來重建物件。只要能控制位元組流,就能讓目標機器呼叫你指定的任何函式。

SafeUnpickler 就是 SGLang 對此的答案。它的 find_class 方法會限制反序列化過程中可以解析哪些 Python 模組、類別與函式,依靠兩套機制:一份「安全」模組前綴的允許清單(ALLOWED_MODULE_PREFIXES),以及一份必須封鎖的特定模組與名稱組合的黑名單(DENY_CLASSES)。

設計意圖完全正確。實作卻有兩個缺陷,而兩者相加,證明是致命的。

缺陷一:一個什麼都允許的前綴

第一個問題:允許清單裡包含了 builtins. 這個前綴。由於前綴比對的緣故,builtins 模組裡的任何名稱都會被放行,除非該名稱被明確列入黑名單。實際上的政策因此變成:「Python 所有內建函式皆可使用,再扣掉一小份封鎖清單。」

第二個問題:封鎖清單不完整。它擋住了最顯眼的幾把槍——eval、exec、compile、open——卻沒有擋住 __import__ 和 getattr。

光這兩個遺漏,就足夠讓攻擊者完成整條攻擊鏈。公開的概念驗證(PoC)只用三步:

  1. builtins.__import__("os")——匯入 os 模組。__import__ 是 builtins 函式,允許清單直接放行。
  2. builtins.getattr(os_module, "system")——用 getattr 取出 os.system。同樣是被允許的 builtins 函式。
  3. 呼叫取出的函式並傳入攻擊者控制的參數——在 PoC 中就是 os.system("touch /tmp/poc_confirmed")。

關鍵細節在於 find_class 檢查的對象。它在解析過程中只看得到傳給它的模組與名稱組合:builtins.__import__ 和 builtins.getattr。它從頭到尾都看不到 ("os", "system") 被直接解析,因為那個解析發生在合法函式的呼叫內部,而不是經過反序列化器的類別查找路徑。黑名單從未觸發。用 VicOne 分析裡的話說:這些限制不是被「打破」的,而是被「遵守」著繞過的。

一個「可選」驗證的管理端點

攻擊鏈還需要一條送進來的路,而 SGLang 剛好提供了:/update_weights_from_tensor 端點,標記為 AuthLevel.ADMIN_OPTIONAL。這個端點的設計用途是接收序列化的張量資料——請求中 base64 編碼的 pickle 資料payload——以進行模型權重的線上更新。當伺服器沒有設定 API key 或管理 API key 時,它會直接接受請求,不做任何身分驗證。

只要能連到該 HTTP 伺服器的攻擊者,就能 POST 一個精心構造的 payload 並達成程式碼執行。不需要憑證、不需要沙箱逃逸、不需要任何使用者互動。

從通報到揭露等了兩個月——修補至今仍缺席

揭露時間線本身就是另一個故事。VicOne 研究員 Reuel Magistrado 先向 SGLang 維護者提交了私密的 GitHub Security Advisory,並以 email 追蹤。2026 年 7 月 2 日,一位維護者在 Slack 上承認收到報告——但此後沒有提供修補,也沒有給出修補時程。7 月 16 日,由於專案毫無回應,問題被升級至 CERT/CC 進行協調揭露。CERT/CC 驗證了漏洞,於 9 月 8 日完成 CVE 編號分配,VicOne 則在 9 月 11 日發布完整技術分析。

截至發布當下,官方修補仍未存在。VicOne 建議的緩解措施由 Magistrado 提出,但尚未被驗證為正式修補,且方向是結構性的:放棄對 builtins 模組的寬鬆前綴比對,改用明確的類別允許清單,只納入張量序列化真正需要的類別——或者整個捨棄通用允許清單的做法。在修補推出之前,所有運行 SGLang 的組織都應為伺服器設定 API key 驗證,並將該端點的存取限制在可信網路內。

18 天內的第四個關鍵 CVE

CVE-2026-86793 並不是孤立事件。Forkast 的分析將它定位為 18 天窗口內的第四個關鍵資料點:

  • 8 月 25 日——Ollama 推論後端漏洞(CVSS 8.1):後端綁定到所有網路介面且停用 Host header 驗證,結合 DNS rebinding,攻擊者只需讓受害者造訪一個惡意網頁,就能取得 Ollama API 的完整未驗證存取權。
  • 9 月 8 日——DeepSeek Harness(CVSS 9.4):首個被證實的 agent 執行環境沙箱逃逸。本地埠上暴露了一個未驗證的 API,而 OS 沙箱又讓 loopback 網路保持暢通,結果容器內一條 curl 指令就能把 agent 權限升級到「danger-full-access」並關閉所有審核提示。
  • 9 月 8 日——IBM Langflow(CVSS 9.8):圖建構階段的未驗證遠端程式碼執行。程式碼掃描器的黑名單漏掉了程序生成原語,而 lfx CodeParser 更是把回傳型別註解直接未經消毒地餵給 eval。
  • 9 月 11 日——SGLang(CVE-2026-86793):即本文所述的 SafeUnpickler 旁路。

這條貫穿線令人不安。這四個框架——NemoClaw、DeepSeek Harness、IBM Langflow、SGLang——都是為了讓模型、程式碼與本地環境之間的高速互動變得容易而生的,而每一個都在「整合便利性」與「嚴格存取控制」之間選擇了前者。光是 DeepSeek Harness 就在釋出後數週內衝上 21.5 萬個 GitHub star,這意味著不安全的預設值在資安團隊來得及部署補償性控制之前,就已經被大規模上線。

而攻擊目標的層級還在不斷下探。這個「驗證缺口」已經從中介軟體一路穿過企業軟體、VPN 基礎設施、網路管理平面,進入 agent 執行環境——現在更觸及推論伺服器本身:那個載入模型權重、處理張量、對外提供預測的元件。當驗證在這一層失效,爆炸半徑涵蓋伺服器上託管的每一個模型,以及依賴它的每一個應用。

揭露頻率也用數字說了同樣的故事:關鍵 AI 基礎設施 CVE 從 2025 年的約每月一個,加速到 2026 年第三季的約每週一個。對於運維 LLM 基礎設施的團隊來說,VicOne 結語中的原則就是最實用的行動指南:安全的反序列化不能只依靠封鎖已知危險函式。為序列化資料採用嚴格限縮的允許清單、為管理端點強制身分驗證,已不再是可有可無的衛生習慣——它是一台推論伺服器與別人的免費算力之間的分界線。