返回所有文章
發佈於 · 作者 Renaud Deraison

為什麼 Bromure Agentic Coding 不是沙盒

沙盒要求開發者拿讓編碼代理人值得一跑的速度去做交換——預先核可每一個相依套件、維護一份網域允許清單、絕不碰一個組織還沒審查過的套件。所以開發者把它關掉。Bromure Agentic Coding 拒絕這場交換。它不限制代理人做什麼;它在 hypervisor 上劃下一條硬線,讓你在裡頭做任何事。這是一篇基礎論述,講為什麼一道邊界勝過一個沙盒,以及這道邊界讓哪三項保證成真:沒有憑證可偷、寬鬆的權杖在線上被收窄、供應鏈攻擊在 tarball 落地之前就被擋下——外加這條線如今讓第四項也成真:提示注入在代理人讀取的內容裡就被逮住,趕在模型聽命之前。

沙盒提出一場交換:放棄一些讓編碼代理人有用的東西,作為回報, 它會保你平安。開發者每一次都拒絕這場交換——他們把沙盒關掉, 或從來不打開——而他們是對的。代理人的工作,就是在雜亂、未經 審查的地帶裡快速穿行。Bromure Agentic Coding 不去限制這件事。 它劃下一條硬線,劃在 hypervisor 上,讓你在它裡頭想做什麼就 做什麼。

一篇基礎文章——寫一次,讓其餘的都指向它。不是關於某起事件。 是關於我們為什麼把 Bromure Agentic Coding 做成現在這個樣子, 以及為什麼「它是個沙盒」是我們一直在更正的那句描述。

開發者不是系統管理員。

把一個編碼代理人放上你機器的理由是速度——是具體的那一種: 在晚上十一點,拉一個你公司裡沒人審查過的套件,看看一個點子 站不站得住。試試那個函式庫,跑跑它的範例,不合用就扔掉。 這不是一個該從人身上紀律掉的缺陷。它就是那套工作流程, 也正是這個代理人值得擁有的全部理由。

所以任何要你預先核可每一個相依套件、或要某人維護一份代理人 可觸及的網域清單的模式,都在跟它所保護的東西交戰。它拖慢了 那唯一一件它被部署來促成的活動——而一道礙著出貨的控管,只有 一個下場:被關掉。一道開發者為了把活幹完而關掉的控管,從來 就不是一道控管。

「跑一個私有、審查過的鏡像站」也以同樣的方式錯失了重點:對 實驗而言重要的那些套件,正是還沒人審查過的那些。一個由核可 相依套件組成的鏡像站,是一個由昨天的點子組成的鏡像站。

所以問題不是怎麼阻止開發者碰未經審查的程式碼。他們非碰不可; 那就是工作。問題是怎麼讓他們自由地碰它的全部,又不把他們的 鑰匙圈也算進這筆交易裡。

為正式環境打造的沙盒,不合工作台的用。

第一個會去搆的是網路沙盒——那些加固過的容器、NVIDIA 的那些、 四處流傳的 Docker-Compose 食譜。形狀總是同一個:列舉代理人 可觸及的主機,其餘一律拒絕。當代理人有一個已知、狹窄的工作 時,它運作得很漂亮。一個只跟三個內部服務和一個模型端點對話的 正式環境代理人,可以永遠住在一份允許清單後面,因為清單很短, 而且不再變動。

發想沒有短清單,而且它從不停止變動。沒人想維護一份白名單, 列出一個實驗可能搆到的每一個登錄檔、CDN、Git 主機,以及一次性 的 API——它永遠做不完、每個下午都在長大,而它擋下某個正當東西 的那一天,就是開發者為了給自己解套而把它停用的那一天。允許清單 本身沒錯;它保護的是一個範圍早已已知的代理人。工作台的全部價值, 就在於範圍還沒被知道。

舉一個具體的下午。一位開發者有些 Node 設定檔長到了數十 MB, 而他們在用的那個 YAML 剖析器被它們噎住了。有好幾個候選—— js-yamlyamlyaml-js——而要知道哪一個能撐過一個 40 MB 的檔案而不把堆積撐爆,唯一的辦法就是三個都裝起來,把檔案丟給 每一個。為了能拿去做基準測試而開一張單,把三個函式庫弄進私有 鏡像站,這正好是反過來的:開發者想要先測試,再把贏家擢升進 鏡像站,而不是倒過來。預先審查,正是那道實驗存在的目的就是要 穿過去的閘門。

底下還有一個更安靜的問題。這些工具加固的是正式環境裡的代理人 ——已部署、有範圍、受監督。但一次供應鏈淪陷落在的是開發者的 筆電上、實驗進行到一半時、~/.aws~/.npmrc 裡擺著真實憑證 之處,因為那就是開發者擺它們的地方。這個模式最強之處是攻擊不在 的地方,而在攻擊所在之處則缺席。

貓抓老鼠的沙盒,輸在第二回合。

另一個直覺是把代理人留在主機上,然後把那個行程關進牢裡—— 封鎖 claude 行程去讀 ~/.ssh~/.aws。它感覺滴水不漏, 直到你想起代理人的工作就是寫程式碼,而程式碼跑在同一台機器上。

代理人搭起一個專案的骨架。然後你——或代理人、或第二個工具—— 在它剛寫好的儲存庫裡跑 npm install。那個 npm install 不是 那個被關進牢裡的行程。它的 postinstall 鉤子像你筆電上任何 其他程式一樣讀 ~/.aws/credentials,因為它正是那個東西: 另一個程式,跟你跑的一切共用著那一個檔案系統和那一個鑰匙圈。

你的筆電 — 一個檔案系統,一個鑰匙圈行程牢claude✗ read ~/.ssh✗ read ~/.aws被封鎖 — 感覺滴水不漏./repo — 代理人剛寫好package.json "postinstall": "node x.js"第二個殼層 — 沒被關進牢$ npm install runs postinstall一個牢從沒具名過的不同行程鑰匙圈~/.aws/credentials~/.ssh/id_rsa~/.npmrc真實權杖✗ 牢拒絕這條路徑讀真實憑證 — 沒人關它進牢
貓抓老鼠的那個漏洞。一道行程牢把 claude 行程擋在鑰匙圈之外(那條虛線路徑,被拒)。但代理人實際的產出——一個帶 postinstall 鉤子的儲存庫——跑在一個牢從沒聽過的手足行程裡。開第二個殼層、跑 npm install,它的 postinstall 就自由地讀 ~/.aws/credentials 並外洩,因為在一台主機上,每個行程都共用一個檔案系統和一個鑰匙圈。那道牢把邊界劃在了錯誤的東西周圍:危險從來不是那個具名的行程,而是那台共用的機器。

那道牢把它的邊界劃在一個行程周圍。危險從來不是那個行程;而是 機器上每個行程都共用一個檔案系統和一個鑰匙圈。所以你打補丁—— 把殼層也關進牢、然後是 node、然後是套件管理器——而攻擊者 不斷找到一扇你沒鎖的門,因為在一台主機上,永遠有另一個行程、 另一條通往同一批祕密的路徑。這就是這場遊戲,而莊家永遠還有 另一扇門。

用 hypervisor 把線劃一次就好。

Bromure 不再陪玩,做法是把邊界往下挪一級。代理人、它生出的 殼層、它安裝的套件,以及那些套件跑的任何程式碼,全都住在一個 按設定檔劃分的 Linux VM 裡。你真實的憑證從不進去。

差別在於這條線的種類。一道行程牢是一條關於某個行程的策略, 而一個手足行程就把它繞過去了。VM 邊界是客體與主機之間那道牆, 由 hypervisor 落實——就是那道阻止一個 VM 去讀另一個 VM 記憶體 的同一道牆。沒有任何系統呼叫能跨越它。裡頭的程式碼推理不出 通往你鑰匙圈的路,因為那個鑰匙圈根本不在它的世界裡。

而在那條線裡頭,你是自由的。裝那個未經審查的套件。跑它的 postinstall。讓代理人改寫你的殼層設定、把磁碟塞滿、弄壞工具鏈。 那個 VM 是可拋棄的,而且從來不曾握有任何要緊的東西。那份自由 就是全部的重點——正是沙盒拿走的、而一道乾淨的邊界還回來的東西。 你不是靠把工作台弄得更沒用來換取安全;你是靠把工作台變成一個 打從一開始房間裡就沒有貴重物品的地方來換取它。

那同一條線,正是三項保證從代理人能推翻的建議、變成在它底下 落實的事實之處——因為 VM 對外做的一切都得跨越它。

那條線讓三件事成真。

按設定檔劃分的 VM — 裝任何東西、跑任何東西、弄壞任何東西代理人 · 生出的殼層 · npm / pip · 不可信的 postinstall 程式碼檔案系統只放 stub — aws_secret = stub-… _authToken = stub-… id_rsa = stub-…這裡沒有東西是真的,所以這裡沒有東西值得偷抓一個套件用一個憑證push / drop / deleteHYPERVISOR 邊界 — 裡頭程式碼跨不過的那唯一一條線① 擋下惡意套件掃描:OSV + socket.dev冷卻:< 2 天則扣住惡意 tarball 永不落地② 沒有憑證可偷stub-token ⇄ real token在線上對換主機掃描找到的是占位符③ 變更前先問讀取放行 · 寫入暫停在主機上提示你看到那個字面呼叫主機 — 真實權杖,在代收者後面~/.aws · ~/.ssh · ~/.npmrc — 從不進入 VM,只在線上換進來,只為一通你允許過的呼叫
一道邊界、三道控管,在代理人底下落實。在 VM 裡代理人想做什麼就做什麼。但每一次跨越都由 hypervisor 居中調度:一次套件抓取會被掃描(OSV + socket.dev),若它比冷卻期還年輕就被扣住;一次憑證使用會碰上一個 stub,主機代理在線上把它換成真實權杖、再換回來;一次會改變狀態的寫入會暫停,在主機上跳出提示。真實的鑰匙圈坐在線的下方,從不進入 VM。代理人沒辦法繞過其中任何一項,因為跨越邊界除了穿過它之外沒有別的路。

沒有憑證可偷——祕密從來不在房間裡。

真實權杖留在主機上。VM 拿到的是 stub:語法上有效、但內容在 公開網際網路上毫無意義的憑證檔。當代理人發出一通需要真實權杖 的正當呼叫時,一道主機代理在線上把 stub 換成真正的祕密,再從 回應裡把它換回去。一個淪陷的相依套件,把檔案系統掃過一遍找 ~/.aws/credentials~/.npmrcid_rsa,找到的是占位符。 這就是權杖對換:憑證存在,代理人拿它去做它該做的事,而那份 可能被偷走的副本,不存在於代理人世界搆得到的任何地方。

收窄那個寬鬆的權杖——用之前先問,變更之前先問。

真實權杖通常比任務本身更寬。代收者讓授權維持短命且有範圍,而且 ——這是它真正值回票價的部分——對讀取和寫入區別對待。讀取放行。 一通會改變狀態的呼叫——一個 git push、一個 DROP TABLE、 一個 AWS Terminate*——在邊界上暫停,並在主機上問你,顯示那個 字面操作,而不是代理人寫的一份摘要。

那改變了一個寬鬆權杖所意味的東西。一個能刪掉正式環境的權杖, 只有在一個真人看過了那通確切呼叫並說好之後才能這麼做;印在憑證上 的範圍,不再是爆炸半徑。代理人沒辦法替自己預先核可、把模式降級、 或讀到那次授權——決定住在線的另一端。當一個代理人在九秒內刪掉 了一個正式環境資料庫時, 原則是同一個:那個想執行指令的東西,不該是那個判斷它安全的東西。

別當第一個發現的人——供應鏈擋在門口。

擋下一個下了毒的套件,最好的時機是在它落地之前。每一次抓取都 跨越邊界,所以代理會掃描它——OSV 抓已知的 CVE,socket.dev 抓資料庫還沒逮到的:流氓安裝腳本、打錯字搶註、一小時前才發布的 淪陷。而且它落實一段冷卻期:過去兩天內(可調)的任何發布版本, 在生態系跟上之前就是裝不了。一隻蠕蟲的整段窗口,就是發布撤回之間的那段空檔;拒絕一天大的套件,就是拒絕去當那隻金絲雀。 postinstall 鉤子在進來的路上就從 tarball 裡被剝掉、雜湊修正過 讓安裝仍能驗證——所以落地的套件落地時是惰性的。這一切都沒要開發者 去審查任何東西。他們想拉什麼就拉什麼;邊界就是那個在等著的東西。

其他方案止步之處

多數工具只守住一層。 Bromure 全都守住。

隔離、把密鑰擋在代理人之外、約束這些密鑰的使用方式、掃描供應鏈、攔截提示注入——這個領域往往只挑其中一項。下面把同一套代理人威脅模型套用到人們常用的工具上,看看每個工具到哪裡就止步了。

防護
Dev ContainerVS Code
nonokernel sandbox
agent-vaultoctokraft
Agent VaultInfisical
Docker SandboxesmicroVM
BromureAgentic Coding
隔離邊界
影響範圍在哪裡被擋住
同一容器,共用核心
核心白名單,無獨立核心
代理人就地執行
僅代理;代理人未隔離
microVM,獨立核心
硬體 VM,獨立核心
把密鑰擋在代理人之外
它能讀到真實憑證嗎?
轉發 SSH agent 與 git 憑證
攔截金鑰檔;部分代收
透過管道注入;無讀取路徑
代理在連線上附加
主機代理注入標頭
在連線上替換樁權杖
憑證範圍與核准
按次限制、唯讀、到期、確認
不按使用範圍限制
核准流程 + 出站過濾
按密鑰設 TTL;攔截 shell
按端點出站過濾
網域白名單;VM 內程式仍可使用
按目的地確認 + TTL
供應鏈掃描
攔截惡意/易受攻擊的套件
不掃描套件來源
僅簽章,不掃描套件
不在範圍內
不在範圍內
不掃描套件
Age-gate、OSV、socket.dev
提示注入偵測
掃描不可信內容與規則檔
PromptGuard + ModernBERT
稽核軌跡
記錄代理人做了什麼
僅容器日誌
不可竄改的本機稽核
請求記錄
請求記錄
完整工作階段追蹤,已加密
供應鏈清單(Enterprise)
記錄取得的每個套件
每個相依套件及裁定,可搜尋
Token 用量(Enterprise)
哪些檔案消耗最多 token
依檔案、儲存庫、模型
完整 — 內建並強制 部分 — 有限或可選 無 — 未涵蓋

隱藏權杖並不等於管控它的使用。Docker Sandboxes 讓真實值不進入 VM,但它的代理仍會把該憑證附加到沙箱送出的任何外送請求上;於是一個在旁邊被植入的惡意套件,即使從未看到這個值,也能拿它去存取白名單內的服務。只有 Bromure 會在套件執行前先掃描它,並對每一次使用加上確認、唯讀與 TTL 限制——在代理人無法繞過的單一邊界上強制全部五項控制。

依據各專案的公開文件整理,2026 年 6 月。這裡的 agent-vault 指 octokraft/agent-vault(基於管道的密鑰注入),有別於 Infisical 的 Agent Vault(HTTP 憑證代理)。Docker Sandboxes 仍是實驗性預覽,其代收的憑證對 VM 內的任何程式都保持可用。全設備的套件清單與 Token 用量彙總由 Bromure Enterprise Manager 提供。這些工具更新很快——發現過時之處?告訴我們。

第四件事:資料裡的一條指令,不是一道命令。

上面那三項保證共享著一個值得攤開來說的假設:它們防的都是 會拿走某樣東西的程式碼——一份憑證、一枚權杖、一個新鮮 tarball 的執行機會。有一種攻擊什麼都不拿。它只是告訴代理人 該做什麼。埋在代理人讀的 README 裡的一行字、抓取頁面裡的 一個字串、某個工具輸出裡的一句話、藏在被代理人當成常備指令 的 CLAUDE.md 裡的一條指示——模型把它當成情境攝入,再把它 當成指令照辦。外洩那個檔案。削弱那項檢查。跳過那個測試。 沙盒對這一切沒有任何意見,因為沒有任何東西跨過一道它看守的 牆:那條指令是以資料的身分抵達的,裝在代理人本來就該讀的 內容裡。

但它確實跨過了那條線——模型看到的一切都跨過。所以從 2.4.0 起,邊界會先讀它,在裝置上、在主機 這一側。一個本地的 PromptGuard 分類器會為流向模型的不受信任 內容評分——檔案讀取、網頁抓取、工具輸出——找出根本不該出現 在那裡的指令。而代理人不加質疑就服從的規則檔案——CLAUDE.mdAGENTS.mdGROK.md——則得過一道更嚴的雙重關卡:一道 決定性的掃描,抓不可見 Unicode、雙向文字花招,以及「忽略 先前指令」這類元指令;再加一個經過微調的 ModernBERT 分類器, 抓關鍵字過濾會漏掉、語氣平和的濫用。力道由你逐設定檔挑: 記錄進 Security Log、詢問並看到被標記的文字,或在模型 看到那段被下毒的文字之前就攔截請求。什麼都不會離開那台 Mac。

這個擺放位置,跟其他三項是同一個論證。一個已經吞下注入的 代理人,不能被信任會回報它——注入的第一條指令,通常就是某個 版本的別提這件事。偵測器不去問代理人。它在線的另一側讀 流量,在代理人的話術搆不到的地方。

那條線救不了你的地方。

一道邊界是一個特定的形狀,不是一句魔咒。四個老實的邊角:

設定檔長命,所以持久性會持久下去。

一個 Bromure 設定檔不是一塊可拋棄的磁碟。一個把自己寫進 啟動路徑的酬載,可以在下一個工作階段裡醒來——醒來面對一個 沒有主機金鑰的客體,和一個只說短命、要先問、有範圍權杖的 代收者。身處一個什麼都沒有的房間裡,但身處依舊。

一個你核可的寫入,是一個會發生的寫入。

那個提示逮住的是代理人沒告訴你的那通呼叫。它不讀你的 diff。 核可一個 git push,Bromure 就轉發它——原則上,包括一個你 沒注意到、下了毒的工作流程。它把決定移到你身上,並顯示那個 真正的操作;讀懂它仍然是你的工作。

冷卻期是一扇窗,不是一堵牆。

兩天是照觀察到的發布到撤回空檔調過的。一個有耐心的攻擊者, 可以蹲在一個淪陷的版本上、撐過冷卻期,到第三天就能被裝起來。 它餓死當天的蠕蟲;它不為一個只是純粹放久了的套件背書。 socket.dev 和 OSV 仍然得各盡其職。

刻意去設定代收者的範圍。

隔離框住的是爆炸;設定範圍決定它本來能有多大。一個只讀一個 儲存庫的設定檔,不該握有一個能寫它的權杖;一個從不發布的, 不該握有任何發布權杖。那條線把祕密擋在 VM 之外——而到底 哪些祕密存在,仍然是你說了算。

我們會守住的那條線。

這就是那份承諾。一個開發者不該為了保住自己的鑰匙圈,就得變成 一個系統管理員——維護一份允許清單、預先放行每一個相依套件、 放棄那讓代理人值得一跑的速度。沙盒把安全弄成了一場拿有用性 去做的交換,而開發者明智地一直選擇有用性。一道邊界拒絕這場 交換:在裡頭做任何事,因為裡頭是可耗費的,而那四件要緊的事—— 你的憑證、你權杖的範圍、搆到你的套件、搆到你模型的指令—— 是在一條裡頭程式碼吵不過的線上被決定的。

這就是為什麼「它是個沙盒」是我們會一直更正的那句描述。沙盒 限制代理人。Bromure 限制邊界,並把代理人放自由。Bromure Agentic Coding 是免費、開放原始碼、今天就 出貨的。