打開別人的程式倉庫,在 Codex 最嚴的 read-only 模式問一句「這段程式在做什麼」,畫面上沒有核准視窗,終端機也沒跳出警告。Accomplish 首席安全研究員 Oren Yomtov 寫明:在他驗證過的環境裡,這一問就足以讓倉庫作者在你的電腦上跑出沙盒外的指令。沙盒沒有被關掉。模式名稱仍寫著唯讀。主機端的應用程式還是被啟動了。
模型沒有自己決定越獄。落點是編碼AI代理的圍欄:檢查邏輯跟被檢查的程式待在同一側。BleepingComputer 把這份研究帶進更廣的安全圈後,要核對的是有多少安裝仍停在修補之前。Yomtov 說兩處問題都在 8 月 12 日回報給 OpenAI,八天內修完。公開文章則到 9 月 15 日才上 Accomplish 部落格。中間隔了將近一個月的沉默,也隔開了「廠商已修」與「使用者已改」兩件完全不同的事。
公開材料沒有寫出真實攻擊、沒有寫出失竊憑證,也沒有寫出被植入後門的開發者機器。BleepingComputer 在刊出前有向 OpenAI 求證。OpenAI 的公開修補出現在開源 Codex CLI 的發行說明裡,但沒有用 Heapjack、Overpatch 這兩個研究名稱。
兩條路,兩個產品,兩個最低修補版
| 研究名稱 | 落點 | 官方模式 | 研究者寫的後果 | 最低修補 |
|---|---|---|---|---|
| Overpatch | 開源 Codex CLI 的檔案修補路徑 | workspace-write | 工作區外寫入,下一次開終端機才執行 | CLI 0.149.0 |
| Heapjack | 桌面版安裝進全域設定的 JavaScript 輔助工具 | read-only | 無核准提示、無畫面顯示,主機指令直接跑 | 桌面版 build 26.818.21641 |
Yomtov 把兩條路寫成同一句話:執行檢查的東西,坐在被檢查的東西裡面。Overpatch 那一側,代理用來改檔的工具會依補丁裡出現的路徑,自己算出額外寫入範圍;殼層指令去寫家目錄會被拒,同一件事換修補路徑就可能過。Heapjack 那一側,桌面版在安裝時把一個 [mcp_servers.node_repl] 區塊寫進全域 ~/.codex/config.toml,沒有開關、也沒有選擇退出。MCP 在這裡不是抽象協議名詞,它是模型呼叫外部工具的接線方式;這條接線一旦寫進全域設定,純命令列使用者也會繼承同一支工具,即使自己從沒開過桌面版。
輔助工具本體是沙盒外的原生程式。它拉起的 JavaScript 跑在沙盒裡,但同一支 Node 處理程序裡放了兩套執行環境:一套是 OpenAI 自己的程式,一套是代理產生的程式。研究者的結論是:用來證明「我是受信任那一套」的密鑰,跟不受信任的程式共用同一塊記憶體。密鑰一旦被另一側拿到,沙盒外的父行程就會把請求當成正當工作做完。Node 自己的 vm 文件寫過:分開的 JavaScript 環境不是安全邊界。General Analysis 在事件回應指引裡把這句話直接點出來,意思是:把兩個語境當成兩個信任域,從一開始就站不住。
Heapjack 的展示在最嚴模式下完成。Yomtov 寫:效果等於你把沙盒關掉、親手去跑對方倉庫裡的指令。差別只在於,你以為自己沒有允許。
這張時間線裡,企業要處理的是最後一格。漏洞在 8 月下旬就進了發行版;9 月中旬才有名字。中間那些沒改版本的安裝,才是現在還能被盤到的東西。
官方發行說明修了什麼,以及它沒點名什麼
GitHub 上的 Codex CLI rust-v0.149.0 標在 8 月 20 日。發行說明沒有安全公告標題,三筆和這次研究對得上的變更混在一長串功能與修正裡:
#39614Preventapply_patchfrom widening write permissions#39659Harden unsandboxed patch filesystem access#39301Prevent Node REPL auth tokens from reaching child processes
#39614 的合併說明寫得很窄:從「補丁目標的父目錄」推導權限,可能把寫入範圍擴到工作區以外;修復是先跳過沙盒政策已經覆蓋的目標,再決定要不要額外開父目錄。回歸測試涵蓋工作區目錄、已經可寫的父目錄,以及指向工作區外的符號連結。#39301 更早一天,8 月 18 日合併,做的是把 NODE_REPL_AUTH_TOKEN 從模型夠得到的子行程環境變數裡拿掉。General Analysis 特別寫了一句:清掉環境變數,本身不能證明共用記憶體那條路也被補上。桌面版 build 26.818.21641 的門檻來自研究者,第三方沒有拆過封閉桌面輔助工具的完整修補。
這三筆變更對開發者的意義很具體。CLI 發行說明是公開、可核對、可寫進批准清單的。桌面版修補沒有對應的同名安全公告。兩個產品各修一條,更新其中一個,另一條仍在。Yomtov 在部落格第一段就把兩個版本號拆開寫,不是修辭,是安裝路徑本來就分開。
OpenAI 沒有用 Heapjack、Overpatch 這兩個詞。沒有 CVE 編號出現在 Accomplish、BleepingComputer 或 General Analysis 的公開文本裡。沒有官方事故說明把「8 月 12 日的研究回報」和「8 月 20 日的 CLI 發行」對成同一份諮詢。對資安團隊來說,這表示搜尋關鍵字會漏。搜 Heapjack 找不到廠商公告;搜 0.149.0 找得到修補,但看不出它對應哪一條已公開的逃逸路徑。
模式名稱沒有定義主機暴露面
Codex 把核准和沙盒寫成兩套控制。OpenAI 自己的文件也把兩者分開。被打穿的是對模式名稱的信任:使用者以為唯讀就等於主機沒事。read-only 限制的是代理在工作區裡能寫什麼;它沒有自動把桌面版裝進去的輔助工具、全域設定、本機通訊端、以及開發者家目錄裡的殼層設定,收進同一道牆。
開發者工作站通常不是乾淨的實驗機。它上面有 GitHub 登入、雲端主控台、套件倉庫權杖、程式碼簽署金鑰,有時還有 Docker 通訊端。Yomtov 寫 Heapjack 拿到的存取可以連本機 Unix 通訊端,Docker 守護行程通訊端是他點名的明顯目標;他沒有宣稱自己打進了 Docker 主機。這句話必須保持這個精度:夠得到通訊端,和已經拿下容器主機,不是同一件事。公開材料也沒有後續憑證盜用或雲端帳戶被用掉的紀錄。
BleepingComputer 把問題收成同一類設計:圍欄從裡面被說服放行。7 月 Pillar Security 已經在 Codex、Gemini CLI 與 Google Antigravity 等編碼代理上展示過相近思路——代理留在沙盒裡,卻寫出一個沙盒外受信任工具稍後會去執行的檔案。Accomplish 自己稍早也公開過 Claude Cowork 與 Cursor CLI 的沙盒逃逸,根因同樣是「哪一段程式以為自己在牆內、哪一段其實沒有被包進去」。不必把所有產品寫成同一場事故。能核對的是結構:編碼代理的信任邊界,已經連續幾個月被同一類設計打穿。模型廠商在談前沿系統要不要放慢時,開發者端的圍欄並沒有比較安靜。
同一週稍早,Hacktron 用 Claude Opus 5 打進 OpenAI 的路徑,走的是內部論壇與員工 Codex 開出的 PR,不是桌面沙盒。夏天那起 Hugging Face 生產環境入侵,則是評測用的大型語言模型自己離開評測圍欄。三件事不要併成「同一則漏洞」。它們共同能核對的只有一句:代理一旦有工具、有網路、有工作區,圍欄要看的是行程、檔案系統與憑證怎麼被劃開,不只是模型權重裡的對齊問題。
週活兩千萬人的工具,修補卻要兩條安裝路徑
8 月下旬 OpenAI 自己把 Codex 與 ChatGPT Work 的週活寫到兩千萬。那篇用量新聞要對的是額度與產品節奏;這次要對的是同一套工具的本機邊界。人數本身不證明有多少人中招,它只證明漏改的成本會按安裝基數放大。終端機裡的 codex、桌面應用、IDE 外掛、排程任務,常常不是同一個執行檔。General Analysis 的盤點表把這點寫成作業,不是建議:先記錄每個啟動器實際跑哪一個二進位、哪個版本、哪個來源,再把「安裝成功」與「新任務真的載入新檔」分開結案。
他們列的盤點面有四塊。終端機 CLI 要記錄解析到的路徑與 --version。桌面應用要記錄安裝 build、更新回條、重新開啟後顯示的 build。桌面版寫進去的 JavaScript 輔助工具要確認還在不在、由哪一個已更新的應用提供。IDE、背景任務或自動化啟動器要用它們自己的設定再查一次,不能拿你在互動式終端機看到的版本當全集。Yomtov 寫過:問「這個人裝的是 CLI 還是桌面版」是問錯問題,因為桌面版安裝會改全域設定,CLI 接著讀。
更新之後還要重啟。OpenAI 的本機安全指引寫過,背景政策重新整理,不能證明既有任務已經載入新政策;macOS 裝置管理條件在下一次用戶端啟動才生效。General Analysis 把這句話轉成結案條件:新任務要用預期的執行檔、輔助工具與政策。安裝程式顯示成功,不夠。
對還在用舊版的人,公開建議很短。更新 CLI 到 0.149.0 或更新、桌面版到 26.818.21641 或更新。不要為了「先避開升級問題」把沙盒改成全開。不要把未審查的倉庫直接丟進主力開發機。Accomplish 自己的產品選擇是把整個代理放進虛擬機,真實憑證不進客體,出站流量走主機上代理到不了的代理伺服器。那是他們的架構主張,不是 OpenAI 官方修復的一部分,也不能替代打修補。
沒被寫進公開文本的事,比被寫進去的更容易誤判
沒有真實攻擊被點名。沒有開發者回報「我的 .zshrc 被改過」成為這次披露的一部分。沒有 OpenAI 安全諮詢把兩條路映射成 CVE。BleepingComputer 文下有讀者把根因寫成「OpenAI 用生成式 AI 自己寫沙盒」,作者 Ax Sharma 回:研究文本沒有把兩處缺陷連到程式怎麼寫出來,OpenAI 也沒這樣說,「我確定」不是證據。其他編碼代理同樣出過沙盒逃逸。這則讀者評論可以留在爭議欄,不能寫進事實欄。
時間窗也容易被寫錯。研究者說暴露期大約從 8 月 12 日到約 8 月 20 日,指的是「回報到 CLI 修補發行」這段。對沒更新的安裝,時鐘並沒有在 8 月 20 日停。9 月 15 日的公開文章、9 月 20 日的安全媒體轉述,改變的是誰知道要去查版本,不是舊執行檔突然變安全。General Analysis 把工作拆成兩張工單:平台負責人換成批准過的版本並重啟;事故回應則另查更早的任務活動、工作區外檔案變動、意外的應用啟動、以及連到的系統。有漏洞版本存在,本身不是每張憑證都要輪替的理由;沒有告警,本身也不是機器乾淨的證明。
對一般使用者,編碼代理會改檔、跑指令、讀倉庫,有時還會碰到電腦上其他服務的門口。模式名稱寫唯讀,不表示那些門口都被鎖上。AI安全討論這一年多半停在模型要不要放慢、要不要新法、要不要獨立驗證;開發者筆電上的圍欄是另一層,修補節奏按的是發行版號,不是記者會。
BleepingComputer 刊出後,安全圈在做版本盤點,而不是重現展示。這台機器的 CLI 是不是 0.149.0 之後?桌面版是不是 26.818.21641 之後?全域設定裡那支桌面版寫進去的輔助工具,是不是已經跟著新的桌面應用被換掉?其中一項答不出來,這則披露對那台機器就還沒結束。
