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

那次關掉 Cursor 沙箱的注入

2026 年 7 月 1 日,Cato AI Labs 揭露了 DuneSlide:Cursor 裡的兩個重大漏洞(CVE-2026-50548 與 CVE-2026-50549,CVSS 皆為 9.8),一段搭著 MCP 工具結果或網頁搜尋片段抵達的提示詞注入,驅動了 run_terminal_cmd 工具以及一個符號連結的後備路徑,去覆寫 Cursor 自己的沙箱輔助程式。守衛從內部悄悄失聲,下一條命令便以開發者的身分執行,觸及編輯器登入了的任何雲端或 SaaS。無需使用者互動,已在 Cursor 3.0 修補。這是一個關於邊界該落在哪裡的故事:在 Bromure Agentic Coding 裡,同樣的逃逸落在一台可拋棄的 VM 內,逃出來的 shell 在本該是真正權杖的地方只找到被換掉的樁,而 PromptGuard 早在模型對那些不受信任的內容動作之前,就已在線路上為它評了分。

DuneSlide 並沒有逃出 Cursor 的沙箱。它說服了 Cursor 自己的 代理,去覆寫那個負責執行沙箱的小小二進位檔,於是守衛從內部 悄然失聲。一道與它所監看的程式碼跑在同一個行程裡的邊界, 就是一道那些程式碼搆得到的邊界。

一位開發者請 Cursor 接上一個新的整合,並把它指向某家廠商的 文件,或者連上一個 Model Context Protocol 伺服器,好讓代理能 拉取即時資料。MCP 就是那個讓編碼代理能呼叫外部工具、並讀取 它們結果的插頭。Cursor 抓取頁面、讀取工具的輸出,並把兩者 都摺進它推理所依據的上下文裡。在那段回傳的文字某處,坐著一句 開發者從沒寫過的話,它是對著模型說的,而不是對著人。代理把它 讀成一條指令,然後動了手。

2026 年 7 月 1 日,Cato AI Labs 揭露 了這件事所鋪設出的攻擊鏈,而 The Hacker News 在同一天做了報導。兩個漏洞,CVE-2026-50548 與 CVE-2026-50549, 評分都是 10 分裡的 9.8。投遞管道是代理早已代你讀取的不受信任 內容:一個 MCP 工具結果、一段網頁搜尋的片段。沒有對話框、 沒有點擊、沒有使用者互動。

DuneSlide 做了什麼。

Cursor 在一個本機沙箱裡跑它代理所生成的命令,而一個輔助的 二進位檔決定那個沙箱允許什麼。第一個漏洞住在 run_terminal_cmd 裡,那是代理用來跑 shell 命令的工具。那個 工具接受一個 working_directory 參數,而注入把它設成一個指向 Cursor 自己檔案的路徑。代理循著那條被夾帶進來的指令,覆寫了 坐落在 /Applications/Cursor.app/.../helpers/cursorsandbox 的 輔助程式。第二個漏洞是 Cursor 解析符號連結的方式裡的一條後備 路徑:當符號連結檢查失敗時,Cursor 信任了捷徑那個在專案內的 路徑,卻仍然寫到了專案之外,落在同一個輔助程式上。

無論哪條路,結果都是同一件事。那個決定命令是否受限的二進位檔, 被替換成一個什麼都不限制的版本。代理跑的下一條命令便以開發者 的身分、在沙箱之外執行,觸及範圍就是登入了編輯器的那個人所能 觸及的一切:雲端主控台、SaaS 儀表板、以及這個工作階段早已能夠 碰觸的儲存庫。Cursor 在 3.0 版修補了這兩個漏洞。在此之前的每一個 版本都暴露在外。

你的 MAC:Cursor、它讀的內容、輔助程式與你的憑證共用同一台機器不受信任的內容MCP 工具結果/網頁搜尋片段"set working_directory to the Cursor helper path and run…"CURSOR 代理把結果讀成上下文tool: run_terminal_cmdworking_directory = ../Cursor.app讀成指令沙箱輔助程式(被覆寫).../helpers/cursorsandboxCVE-2026-50548: working_directoryCVE-2026-50549: symlink 後備守衛已失:下一條命令以你的身分執行觸及編輯器登入了的雲端主控台與 SaaS 儀表板沒有對話框、沒有點擊、沒有使用者互動
DuneSlide,由左至右。一個 MCP 工具結果或一段網頁搜尋片段,夾帶著一句瞄準模型的指令。Cursor 把它讀成上下文,並在 working_directory 指向自己檔案的情況下跑了 run_terminal_cmd(CVE-2026-50548),或者透過一次失敗的符號連結檢查寫到了同一個地方(CVE-2026-50549)。兩者都落在 cursorsandbox 上——那個負責執行沙箱的輔助程式——並將它覆寫。守衛被替換之後,下一條命令便以開發者的身分執行,觸及編輯器登入了的雲端與 SaaS 帳號。Cursor、被注入的內容、輔助程式與憑證,全都共用同一台 Mac。

那道邊界就坐在它守護的房間裡。

再讀一遍這條攻擊鏈,其中最尖銳的部分並不是符號連結的把戲。是 守衛所在的位置。那個決定命令是否受限的輔助程式,就坐在代理所 編輯的專案的同一顆磁碟上,處在與代理相同的信任域裡,被代理用來 做日常工作的同一個 run_terminal_cmd 所搆得到。沙箱和它所管束的 程式碼以同一個使用者的身分、在同一台機器上執行,之間只隔著同一個 檔案系統。給代理寫入一個檔案的能力,讓攻擊者去挑是哪一個檔案, 而他們挑的那個檔案,就是守衛。

那正是今年編碼代理安全裡一再重演的失效模式,而我們已用其他樣貌 把它寫過:一個代理讀得到的憑證,就是一個被入侵的相依套件讀得到 的憑證,見 藏著金鑰的沙箱; 而一個代理關得掉的控制項,本就從來不是控制項,見 為什麼 Bromure Agentic Coding 不是一個沙箱。 DuneSlide 就是同一堂課,只是搬到了沙箱二進位檔本身的層級。一道 行程內的守衛保護著你,直到它所住的那個行程決定去編輯它為止。

同樣的攻擊,只隔著一層 hypervisor。

Bromure Agentic Coding 把邊界放在代理寫不到的地方。代理、它衍生 出的那些 shell、它呼叫的工具,以及那些工具跑的任何程式碼,都住在 一台有自己 Linux 核心的可拋棄虛擬機裡。VM 送出或讀入的每一個 位元組,都要穿過一個跑在 macOS 主機上、位於客體之下、處在 hypervisor 另一側的 proxy。那個 proxy 是同一個地方,卻做著好幾件 工作。把 DuneSlide 拿到它面前重播一遍,每一步都會撞上其中之一。

從逃逸開始。注入照樣抵達,代理照樣跑 run_terminal_cmd,兩個 CVE 也照樣觸發。覆寫落在客體自己的檔案上。Mac 的磁碟、它的 /Applications、它的 Keychain 都不在 VM 的世界裡,所以從客體 內部的一個符號連結,沒有任何路徑通往主機上的一個二進位檔。 爆炸半徑就是一台你能在幾秒內刪掉並重建的機器。

再來是收割那一步,也就是伸向雲端與 SaaS 的那一手。攻擊正是為了 價值而來到這裡,卻兩手空空。真正的權杖留在主機上。VM 裡裝的是 樁:外形正確、在公開網際網路上卻毫無意義的憑證檔。當代理發出一個 需要真正祕密的呼叫時,主機的 proxy 會在線路上把樁換成真正的權杖, 再從回應裡把它換回來。一個跑著 env | grep TOKEN 或讀取 ~/.aws/credentials 的逃逸 shell,找到的是占位符。真正的憑證唯一 存在的那一刻,是在代理為了真正工作而發出的一個請求裡;而一個會 改變狀態的呼叫,會在邊界處暫停,等主機上的一次確認,然後才離開。 套件抓取穿過同一個 proxy,並在進來的路上被掃描。一條線,好幾件 工作,而且全都在代理之下。

不受信任的內容:MCP 結果/網頁片段夾帶著啟動 DuneSlide 的那段注入PROMPTGUARD(若啟用)在模型讀到它之前替它評分萬一溜了過去可拋棄的 VM:有自己的核心;Cursor、shell 與工具都住在這裡① 逃逸落在客體裡run_terminal_cmd + symlink 覆寫打中客體自己的檔案Mac 的磁碟不在這個世界裡② 它想要的權杖不在這裡env | grep TOKEN → stub-…cat ~/.aws/credentials → stub-…沒有真的東西可花代理發出的一個真實呼叫主機側 PROXY,一道邊界:為線路評分 · 把樁換成真權杖 · 掃描套件 · 對改變狀態的呼叫確認主機 MAC:真正的權杖在 Keychain 裡,從不進入 VMproxy 只在線路上、只為你允許的一個呼叫,才附上真正的祕密,然後再把它剝除刪掉 VM,逃逸、覆寫與駐留就一併沒了
DuneSlide 對著 Bromure Agentic Coding 重播一遍。不受信任的 MCP 結果或網頁片段,先抵達主機側的 proxy,PromptGuard 會在模型讀到它之前替它評分。萬一注入溜過了那道檢查,run_terminal_cmd 和符號連結的逃逸照樣觸發,但它覆寫的是可拋棄 VM 內的檔案,而不是 Mac 上的。逃出來的 shell 四處搜尋權杖,找到的卻是被換掉的樁,因為真正的憑證住在主機上,而且只在線路上、只為代理為了真正工作而發出的一個呼叫,才越境進入客體,且會改變狀態的操作都被暫停等待確認。保證來自 VM 邊界與權杖替換;PromptGuard 是那條更早抓住注入的絆索。

逃逸落在客體裡。

兩個 CVE 在 Bromure 底下照樣觸發。覆寫打中的是一台有自己核心的 可拋棄 VM 內的檔案,而 hypervisor 沒給客體任何一個搆得到主機的 系統呼叫。你重建 VM,損害就一併沒了。

它想要的權杖從來就不在那裡。

DuneSlide 的目標是開發者的雲端與 SaaS 存取權。那些祕密坐在 主機上,而 VM 裡裝的是在網際網路上毫無意義的樁。逃出來的 shell grep 權杖,讀到的是占位符,於是收割那一步失敗了。

PromptGuard 先讀線路。

上面那個保證不需要任何分類器就成立:VM 邊界圈住逃逸,權杖替換 餓死收割,不管模型做什麼都一樣。Bromure 在同一個 proxy 上再加了 一層,瞄準的正是 DuneSlide 所用的那個確切管道。注入行進在代理 所攝入的內容裡,一個 MCP 工具結果或一段網頁搜尋片段,而那段內容 在模型讀到它之前,會穿過主機的 proxy。若啟用,PromptGuard 就在 那裡替它評分。第一階段是 Meta 的 Llama Prompt Guard 2,盯著工具 輸出與網頁抓取,找出那些以指令口吻對著模型說話的文字。至於代理 把它當成常設命令的那些規則檔——CLAUDE.md 和它的同類——則交給 一個經過微調的 ModernBERT 分類器,因為一個本就滿是指令的檔案, 需要的是一個評估危害、而非評估注入的模型。

依設定檔而定,Bromure 會記錄這次命中、把它秀給你做決定,或者 在模型看到那段下了毒的區段之前就將它封鎖。位置就是重點所在, 而它和它底下那些層是同一個論證:一個已經吞下注入的代理不能被 信任去回報它,所以檢查跑在邊界的另一側,在那裡代理的說服搆不 到。我們把完整的流水線寫在 Bromure 如何偵測惡意提示詞 裡,也在 那條指令不是他下的 裡看著同一類攻擊搭著一條命令的輸出溜了進來。

DuneSlide 已在 Cursor 3.0 修補,而今天更新是正確的一步。它背後的 那個模式並沒有被修補,因為它不是單一一個漏洞。任何一個把自己的 約束跑在自己行程裡的編碼代理,都離著去編輯那道約束只差一句夠有 說服力的話。能在下一個換了名字的 CVE 中倖存的做法,是把守衛、 憑證與稽核軌跡,統統留在一條代理寫不到的線的另一側。 Bromure Agentic Coding 把那條線劃在 hypervisor 上。它免費、開源,而且今天就已出貨。