那道閘道接受任何一個權杖
9 月 2 日,CISA 把七個已遭利用的漏洞加進 KEV 目錄。其中三個是 AI 基礎設施,這是 AI 佔了將近一半的第一批。讀讀 LiteLLM 那一條:它的 MCP 端點會放行一個帶著任何 Bearer 權杖的未認證請求,因為金鑰驗證失敗後掉進了一個空的認證物件,而呼叫方接著就能列出並呼叫閘道所接上的每一個工具。Bromure Agentic Coding 把同樣的權限放在一個 hypervisor 與一條 vsock 之後:沒有在聽的連接埠、沒有可偽造的標頭、也沒有退路分支。
你建起這道閘道,是為了不讓任何一台筆電握著全部的金鑰。它成功了,於是它握著 全部的金鑰。後來它的前門接受了一個由某人隨口編出來的 Bearer 權杖。
9 月 2 日,CISA 新增了七個漏洞 到 Known Exploited Vulnerabilities 目錄。兩個 SonicWall SMA1000 的問題、一個 Sangoma Switchvox 的 SQL 注入、一個 JFrog Artifactory 的認證繞過、一個 Kestra 的作業系統命令注入、一個 Starlette 的 HTTP 走私缺陷,以及 BerriAI 的 LiteLLM 的一個不當認證缺陷。
這七個裡有三個是 AI 與 ML 基礎設施。Forkast 稱之為 AI 元件佔了新增項目將近一半的第一批 KEV, 那種先掙得一則標題、然後就被歸檔的里程碑。但看看它們是哪一種 AI 基礎設施, 這一批就值得多過歸檔。三個都坐在中間:它們正是你部署下去,好讓你的代理人與 它們所碰觸的資源不再直接對話的元件。就從 LiteLLM 那一條開始。
那條退路分支
LiteLLM 是一道 AI 閘道:一個代理,站在你的代理人與模型供應商之間,替所有人 保管供應商金鑰,執行預算與速率限制,寫下日誌,如今還往 Model Context Protocol 伺服器展開,好讓一個團隊的代理人共用一個 MCP 端點,而不是每位開發者各自接上 自己的。
CVE-2026-59822 於 7 月 8 日公開, 在 GitHub 的公告中帶著 8.8 的 CVSS, 就住在那個 MCP 端點上。公告裡的一句話承載了整個故事:
退路路徑可能以一個空的
UserAPIKeyAuth()物件,取代失敗的 LiteLLM 金鑰 驗證。
MCP Streamable HTTP 端點支援 OAuth2 直通,好讓一個原本要給上游 MCP 伺服器的 權杖能穿過閘道,而不是拿去和 LiteLLM 自己的金鑰庫核對。這是個合理的功能, 而它需要一個分支:先試 LiteLLM 的金鑰,如果送來的不是金鑰,就走直通那條路。
你靠「失敗」抵達那條分支。送出一個 Authorization 標頭,裡面放任何字串都行,
金鑰驗證因為那字串不是金鑰而拒絕它,於是處理程式建出一個空的
UserAPIKeyAuth(),帶著它繼續往下走。你的請求此刻握著一個不屬於任何人的、
已認證的 MCP 工作階段。從那裡,你可以把閘道設定過的每一個 MCP 工具都列出來
並呼叫:內部應用程式、資料庫、雲端主控台、開發系統,團隊接上去的任何東西。
這個缺陷影響 1.84.0 之前的所有版本。CISA 給聯邦機關的修補期限是 9 月 16 日,
而 LiteLLM 給今天無法升級者的建議是:在前面的反向代理上擋掉 /mcp/。
另外三個,壞在同一個函式
把這一批剩下的讀完,你會得到比「AI 對非 AI」那則標題更有用的東西。
Starlette,CVE-2026-48710,綽號 BadHost。Starlette 是 FastAPI 底下的 ASGI
工具組,Python 的 AI 服務有很大一部分建在它上面,LiteLLM 也在其中。一個特製的
Host 標頭把一段路徑注入到請求的主機部分,這改變了 URL 被重建的方式,也就
意味著以路徑為準的認證中介軟體評估的是一條路由,而應用程式端出的是另一條。
CISA 的條目寫明了結果:當認證取決於重建後 URL 的路徑時,會發生認證繞過。它的
CVSS 是 6.5,是這一批裡最低的分數,也是最說不出後果的那個分數。LiteLLM 在
1.84.0 也交出了
針對同一形狀的自家配套修正,
描述為「一個特製的 Host 標頭可能讓代理的認證關卡去評估一條與實際端出者不同
的路由」,並告訴那些代理曾對外曝露的維運者:輪換金鑰,稽核管理日誌。
JFrog Artifactory,CVE-2026-82329,CVSS 9.8。預設組態下的不當認證:一把
「幽靈」join key,讓未認證的攻擊者能偽造管理員權杖。watchTowr 在 9 月 1 日,
也就是揭露後四天,記錄到真實環境中的利用:攻擊者鑄造管理員憑證並列舉使用者。
這是製品倉庫,是替整間組織回應 npm install 與 pip install 的那台主機。
Kestra,CVE-2026-49869。未認證的遠端攻擊者可觸及的作業系統命令注入, 他不需要任何憑證,就能建立並執行任意工作流程。編排器做著編排器該做的事—— 只是替一個從未登入過的人做。
四個產品,四套不同的程式碼庫,而每一套裡壞掉的是同一個函式:決定這個請求 夠不夠格待在這裡的那一個。一個空的認證物件。一條重建出來的路徑。一把預設的 join key。至於 Kestra,是那條負責執行的路由上根本沒有檢查。
攻擊者接下來做的事很無聊,而無聊正是規模化作業的跡象。The Hacker News 整理了觀察到的行為: 反向 shell、XMRig 挖礦程式、憑證列舉,以及竊取 API 金鑰與 LLM 供應商憑證。 Microsoft 總結道:
觀察到的目標是一致的。在這些案例中,遙測資料顯示了憑證蒐集、持久存取機制與 資源變現,儘管執行路徑因產品而異。
閘道是對的主意,而這是它的帳單
AI 閘道是這兩年比較好的主意之一,而多數團隊走到這一步都有紮實的理由。
在閘道之前,每位開發者的編碼代理人都把一把供應商金鑰放在環境變數裡,每位 開發者用自己的權杖接上自己的 MCP 伺服器,而沒有人答得出這一切花了多少、 碰過什麼。在中間放一道閘道,一次就把這些都解決了。一個地方保管供應商金鑰與 MCP 設定,並寫下日誌。輪換一把金鑰變成單一動作,切斷一位離職員工也是。 這個產業會收斂到這裡,是有道理的。
帳單是:你蓋了一個網路服務,它存在的全部意義就是替所有人保管權限,而它用 一個函式來決定你是誰。函式有分支,其中一條分支負責處理「你先試的那件事沒成」 這種情況。
這個形狀不是 LiteLLM 發明的。每一道閘道都有前門,每一扇前門都有一個認證函式, 而一個支援兩種憑證方案的認證函式,會有一條在第一種失敗時走的路。門後那片 觸及範圍是刻意的:把它集中起來,正是這項產品本身。所以當一道閘道出事時, 它保管的一切早就都在同一個房間裡了。
從這種事故通常被導出的結論是「回去用每位開發者各自的金鑰」,而那在任何一項 量測上都更糟。繼續集中。真正值得爭論的問題是那個集中起來的東西坐在哪裡, 以及它是否非得回應陌生人的請求才能完成它的工作。
Bromure 把同一份工作放在哪裡
Bromure Agentic Coding 讓每一個編碼代理人跑在你自己 Mac 上、由硬體虛擬化的 Linux VM 裡,而每一項安全控制都坐在那道邊界的主機側。這些控制和一道閘道提供的 是同一份清單:保管憑證、居中處理 MCP 伺服器、分類代理人對你基礎設施做的事、 留下紀錄。網路上沒有任何東西能碰到執行這些控制的元件。
沒有前門。 客體的 HTTPS 從不經由網路離開。它走一條 virtio 通訊端、vsock
連接埠 8443,隧道到主機端的代理,而手冊對拓樸講得很直白:這台 VM 沒有其他通往
網路的路徑。那個代理沒有任何在聽的連接埠,能讓你的區網、你的公司網路或網際
網路定址得到。它從不問是誰在呼叫,因為那條通訊端的另一端只有一樣東西,而
那是什麼由 hypervisor 決定。沒有 Authorization 標頭、沒有金鑰庫、沒有方案
協商,因此也沒有第一種方案失敗時要走的分支。
MCP 的 bearer 權杖,在抵達代理人之前就已經是假的。 對於工作區裡設定的
HTTP 傳輸 MCP 伺服器,真正的 bearer 權杖始終加密留在 Mac 上。代理人的設定
拿到的是一個 brm-mcp_… 佔位值。設定面板把那個欄位標示為絕不送進 VM——
由代理替換,而主機端的代理會在線路上換進真值,範圍限定為該伺服器主機的完全
相符或子網域相符,別無其他。代理還會對該伺服器的 OAuth 與 OIDC 探索路徑回
404,好讓 Claude Code 把那台伺服器當成已預先認證,而不是去嘗試一段 VM 永遠
完成不了的瀏覽器流程。LiteLLM 的退路,正是站在同一片直通表面上。在這裡,
工作區根本沒有可以失手的憑證。
每一次操作,都有自己的一次判斷。 一道閘道在門口把問題了結:過了門,
後面的一切都是你的。Bromure 的 Guardrails 在代理內部分類代理人的呼叫,橫跨
Kubernetes、AWS、git 託管站、容器登錄庫與資料庫,並套用逐服務的寫入政策。
新工作區預設是寫入前先問,於是讀取照流,而每一次變更都會停在主機側的一個
對話框上,上面顯示字面上的那個操作:確切的 SQL,或 方法 /路徑。唯讀
擋掉一切變更。使用前先問則管住憑證本身,授權以分鐘計。就算是一個偽造的
工作階段,也依然沒辦法靠 kubectl delete 一路推過去,因為第二次判斷發生在
你的 Mac 上,和第一次的結果毫無關係。
預設拒絕,在兩個方向上都回答了可達性。 工作區的出向防火牆是一張有序的 規則表,並為未相符的流量設定預設值。把它設成拒絕,這台 VM 就只能到達你 列出的主機,在任何協定上都是如此。客體之外的兩個元件執行這件事:虛擬交換器 以目的 IP 與從 DNS 側錄到的主機名比對每一條流,而代理再以 TLS 伺服器名比對 一次。編輯不必重開就會送到進行中的工作階段。反方向上,NAT 模式讓這些 VM 待在 你的實體區網之外,除非你刻意發布某個服務,否則外面沒有任何東西能對它們開啟 連線。那些把曝露閘道一網打盡的掃描器,從一台 Mac 得不到任何回應。
一道被拿下的閘道送回來的任何東西,都是不可信輸入。 這一點比那個 CVE 活得
更久。一旦閘道歸了別人,模型輸出、工具結果與錯誤字串就全都來自攻擊者,而且
走在整個堆疊裡權限最高的那條線上:代理人天生就會據以行動的那條。Bromure 的
原始碼偵測器會用一個本地的 PromptGuard 模型,在裝置上,於模型據以行動之前,
為代理人外送 AI 流量中的 tool_result 區段評分,並可以記錄、詢問或阻擋;
一次阻擋會回傳 HTTP 451,模型永遠看不到那段內容。
外洩那一段會朝關閉的方向失敗。 工作區裡的每一份憑證,都是一個只有單一 合法目的地的確定性假貨。代理會掃描每一個外送請求,找出正要前往鑄造範圍以外 之處的假貨;找到時,它一個位元組也不轉發就拒絕請求,暫停這台 VM 並發出警報, 以一列紅色的憑證仲介記錄在 Security Timeline 上。因為當初能被碰到的只有 假貨,真憑證不需要輪換。
如果你今天在營運一道閘道
把 LiteLLM 升級到 1.84.0 或更新;若做不到,就在前面的反向代理上擋掉
/mcp/。接著照 LiteLLM 自己針對 Host 標頭修正給出的建議,把一個曾經曝露的
代理當成一個曝露的金鑰庫來處理:輪換它保管過的供應商金鑰,稽核管理日誌。
聯邦機關在 CVE-2026-59822 上的期限是 9 月 16 日,那是個可以借來用的合理
日期。
那條讓問題變小的規則
在工作區的 Guardrails 面板裡,把未相符流量設成拒絕,然後列出
這份工作真正需要的東西:allow web api.github.com、
allow web registry.npmjs.org、default deny。一個不被允許碰到內部閘道的
工作區,也就不能被拿來穿過任何一道閘道;而且存檔後,政策不必重開就會推送到
進行中的工作階段。
保管機密,不要檢查它
在這樣的一週之後,Bromure 自己架構筆記裡的一行值得重讀:
繞過這道邊界,攻擊者什麼也拿不到,因為這道邊界不是機密被檢查的地方—— 它是機密存在的唯一地方。
閘道是憑證被檢查的地方:一個請求抵達,一個函式檢視它,而那個函式的裁決是 呼叫方與金鑰之間唯一的阻擋。檢查有邊緣情況,也有退路路徑。檢查會掙得一個 CVE、一則 KEV 條目與一個聯邦期限,然後兩個月後在同一個函式的另一條分支上, 再掙得一個。
線路邊界則是憑證所在的地方。沒有東西抵達等著被檢視,因此也沒有裁決可以出錯。
真正的權杖加密躺在一台 Mac 上,工作區握著一個在任何地方都一文不值的 brm-
佔位值,而替換發生在一條只有 hypervisor 寫得進去的通訊端上。
我們在六週內已經把這件事的變奏寫過三次:一個 信任了代理人可以自己寫入的主機名的出向代理、 一個 讀 bash 的方式和 bash 不一樣的命令守衛, 以及 三個編碼代理人,它們的繞過最後都落在某個行程裡的一份真憑證上。 每一次,失守的那個元件都在誠實地做著「評估某件事」的工作,而這正是不變的地方。 評估是比不存在更弱的原語,而我們卻一直把不存在能免費完成的工作,交給評估去做。
把你那些代理人的權限集中起來,是對的決定。請把那個集中起來的東西,放在沒有人 能對它送出請求的地方。安裝 Bromure Agentic Coding, 給每一個代理人一道沒有前門的邊界。