iT邦幫忙

2026 iThome 鐵人賽

DAY 27
0
AI Security

一個 Agent 我查不動,一個我改得動:內部威脅偵測的 30 天系列 第 27 篇

別人寫的 MCP 工具:設定一讀就跑,結果要扣得下

  • 分享至 

  • xImage
  •  

接上別人寫的 MCP 工具,等於讓別人決定兩件事:開機時跑什麼指令,以及哪些文字會送到模型面前。

Cursor 這邊,近一年的公開研究都打在這兩件事上:讓 agent 自己寫設定檔、換掉核准過的指令、改檔名大小寫、把指令擠出安裝對話框,每修一個就有人找到下一條路;工具說明裡藏的指令,人看不到,模型照讀。2026 年 8 月,Cursor 的工作人員確認:還沒有一支 hook 能同時知道結果來自哪個 server、又能把它換掉。

omp 躲不掉第一件事:repo 只附了 Cursor 的設定檔,omp 照樣在模型收到任何請求前把指令跑起來,沒有人被問過;一個設定就能關掉,但要從 --config 帶入,全域設定檔擋不住 repo。第二件事 omp 補得上:它的一支 hook 同時拿得到 server 名稱、換得掉結果,守門員依 server 扣下的結果,連紀錄裡的原文一起拿掉。

這不是一道牆:守門員在呼叫之後才看,server 已經跑過;工具說明它不管;換個說法的指令認不出來;兩個名稱相近的 server,omp 會默默只留一個。

Day26 把瀏覽器帶回來的網頁,扣在結果交給模型的那一關。最後留了一個問題:如果 agent 接上的是別人寫的工具,工具的說明本身就夾著餌呢?

MCP(Model Context Protocol)是讓 agent 接上外部工具的協定。設定檔寫著要啟動哪個指令、或連到哪個網址;連上後,server 回報有哪些工具、各自的說明與參數;agent 呼叫工具,server 交回結果。三段都是別人寫的:指令在你的機器上執行,說明和結果直接進模型的上下文。

OWASP 的 Agentic 十大風險(2026 版)把這類情境放在 ASI04「代理式供應鏈漏洞」:例子包括把指令藏在工具描述裡,以及用相似的名稱冒充正牌服務;設定檔一讀就啟動指令,則落到 ASI05「非預期的程式執行」。

MCP 設定檔不只是設定,它會被執行。

2025 年 8 月 1 日,Aim Labs 公開了 Cursor 的 CurXecute(CVE-2025-54135)。攻擊者在公開的 Slack 頻道貼一則訊息;使用者請 Cursor 透過 Slack 的 MCP server 摘要訊息,agent 讀到後,就照著在全域設定檔加了一個新的 server。新項目立刻啟動;agent 建議的修改,在使用者按下拒絕前就已寫進磁碟,指令在任何人核准前就跑了。Cursor 在 1.3 版修補。

今天只回答一件事:接上別人寫的 MCP server 之後,它的啟動指令、工具說明和回傳結果,在變成你機器上的動作或模型讀到的內容之前,有沒有東西先看過、能不能擋下? 看 MCP,本篇固定問三件事:

  • 看得到: server 什麼時候啟動、工具說明寫了什麼、結果來自哪個 server,本機的監視器看不看得到。
  • 擋得住: 能不能在 server 啟動前、工具呼叫前、結果交給模型前擋下或扣下。
  • 查得到: 事後知不知道哪個 server 跑過、被呼叫了什麼、被扣了什麼。

Cursor 這一側引用別人公開的實驗、安全公告與 Cursor 的文件和論壇;omp 這一側在這台機器上實測。一鍵安裝 MCP 的連結只有 Cursor 有,本篇只引用報告;把自己的 agent 開成工具給別人叫,留到 Day28。

一、同一個 repo,三段都是別人寫的

情境:同事丟來一個 repo,說裡面附了一個查資料用的 MCP 工具,請你讓 agent 用它查一筆資料,再回報結果。你用 omp 的無頭模式跑,沒有人看著畫面。

測試說明:以下情境來自 2026-10-10 的實測,omp 18.2.8,模型 claude-opus-5-5,每種情境只跑一次。MCP server 是我們寫的無害版本:說明、參數說明、結果都只是固定代號,沒有指令;HTTP 版只綁 127.0.0.1,stdio 版只寫自己的紀錄。agent 的 shell 與執行程式的工具一律禁止;金鑰只透過環境變數交付,事後掃過所有紀錄,沒有出現。Cursor 的部分沒有在這台機器實測;完整條件見附錄 A。

你還沒開口,指令就跑了

那個 repo 沒有 omp 的設定檔,只有一份 Cursor 的 .cursor/mcp.json,用 node 啟動一支 server。給 omp 的提示詞只有「回一個 OK」,不需要任何工具。

那支 server 還是被啟動了。它自己的紀錄寫著:啟動它的是 omp,時間在第一次向模型發出請求之前;omp 還向它要了工具清單。整個過程沒有核准事件(實測)。omp 的文件寫明,它會讀 Cursor、Claude Code、VS Code 等工具的設定檔,而提交進 repo 的 MCP 定義是可信輸入,開啟前要先看過(文件)。

換句話說,CurXecute 和 TrustFall 打的那一層,omp 一樣有:誰能在 repo 裡放一份設定檔,誰就能在你按下執行時跑一個指令;無頭模式連「信任這個資料夾嗎」的提示都沒有。

工具說明先到了

換成要用工具的情境:repo 附的 server 有一個工具,說明與參數說明各帶一個代號。一支只記錄、不攔截的觀察用擴充,在第一次模型請求前就從工具清單讀到這兩個代號(實測)。

omp 預設把不常用的工具,包括 MCP 工具,收進 xd:// 這個虛擬路徑:模型用內建的寫入工具,把參數寫到 xd:// 加上工具名稱;這時的寫入工具只轉送,不寫檔(原始碼確認)。這次需要呼叫 MCP 的六場,模型全都這樣叫(實測)。

server 回傳的代號原樣進了 omp 的模型,模型照著回報(實測)。這次的代號無害;Invariant Labs 在 Cursor 上做過同一段路的有害版本(他人實驗),第二節會談。

圖一:一個 repo 附帶的 MCP server,三段都是別人寫的

https://ithelp.ithome.com.tw/upload/images/20261011/20183541wDooGiDD5G.png

這三段各自對應 Cursor 的一組公開研究,下一節逐段比對。

二、Cursor 與 omp,MCP 的三道門

這一節把他人實驗、公開報告、文件、原始碼確認和實測分開講。

第一道門:設定檔一讀就啟動

他人實驗與公開報告(Cursor):

  • CurXecute(Aim Labs,2025-08-01):新的設定項目不經確認就啟動,見前文。
  • MCPoison(Check Point Research,2025-08-05,1.2.4 以前):核准綁在設定名稱,不是指令;核准過的項目,可以默默換掉指令。1.3 起,任何變動都要重新核准。
  • 大小寫繞過(Lakera,2025-10-10,1.6.23 以前):換個大小寫,就繞過設定檔的保護;1.7 修補,11 月又補了 NTFS 短路徑的繞法。
  • TrustFall(Adversa AI,2026-05-07):Cursor CLI 在使用者接受資料夾信任後,立刻啟動專案定義的 MCP server;提示只籠統提到 MCP。
  • 安裝連結:2025 年兩份公告修了對話框不顯示參數、被假冒;2026-07-15 的 DeepJack 指出,到 3.9.8 版,單行欄位仍能把指令後半段擠出畫面。

文件(Cursor 論壇,2026-06-06): 工作人員確認,啟動時會開啟所有已啟用的 MCP server,沒有「用到才啟動」的選項;6 月 17 日表示不在路線圖上。

這一串修補有個共同點:守的是一個檔名、一個對話框;下一份報告,就找到檔名的另一種寫法、對話框看不到的那一段。

實測(omp 18.2.8,2026-10-10): repo 只附 Cursor 的設定檔,omp 在第一次模型請求前就啟動了裡面的指令,0 次核准事件。用 --config 把 mcp.enableProjectConfig 設成 false,指令 0 次啟動;同樣的 false 寫在全域設定檔,repo 自己的 .omp/config.yml 寫回 true,指令照樣啟動。server 連不上時,失敗只寫在 omp 的行程紀錄檔,標準輸出與錯誤輸出都沒提到,工作照樣完成。

原始碼確認(omp 18.2.8): 這個設定的介面說明只寫根目錄的 .mcp.json,實際上排除所有專案層級的來源。設定的優先序是全域 < 專案 < --config < 執行時旗標,專案層級不排除任何鍵;不呼叫模型的檢查,用 omp 自己算出的值確認了這個順序。

第二道門:工具說明,模型讀得到,人看不到

他人實驗(Invariant Labs,2025-04-01,以 Cursor 為 MCP client):

  • 「加法」工具的說明裡藏著指令,要 agent 先讀 MCP 設定檔與 SSH 金鑰,塞進隱藏參數送出;介面只顯示工具名稱,確認對話框也看不到完整參數。
  • 惡意 server 的工具說明,改變了另一個可信 server 寄信工具的行為;也有 server 第一次載入正常,第二次才換成有害的說明。

文件(Cursor Hooks,2026-10-10 讀取): 沒有一個 hook 事件會收到工具清單或工具說明;呼叫前的 hook 看到的是工具名稱、參數與 server 名稱。

實測(omp 18.2.8): 擴充在第一次模型請求前,就讀得到每個 MCP 工具的說明與參數說明。兩個 server 的設定名稱只差一個符號(d27.marker 與 d27-marker),轉成工具名稱後是同一個:omp 只註冊排序在前的 d27-marker,另一個只在行程紀錄檔留一行警告,呼叫全送到被留下的那台。

文件(omp 18.2.8): server 通知工具清單變了,omp 就重新載入、重新綁定;文件沒有提到要重新核准。

第三道門:結果,知道是誰,卻換不掉

文件(Cursor 論壇,2026-08-05): 使用者回報,呼叫後的兩支 hook 各拿一半:afterMCPExecution 知道結果來自哪個 server,回傳值卻被丟掉;postToolUse 能替換模型看到的 MCP 結果,卻不帶 server 欄位。工作人員確認:依 server 決定結果怎麼處理,目前無法表達。

文件(Cursor Hooks 與 MCP,2026-10-10 讀取): 呼叫前的 hook 同時有 server 名稱與拒絕權;hook 當掉或逾時預設放行,要另外設定才擋。預設每次用 MCP 工具前都要核准;Auto-review 模式下,允許清單上的 MCP 工具直接執行。

實測(omp 18.2.8): 用 tools.approval 把工具設成 deny,經由 xd:// 也擋得住:錯誤寫著被使用者政策封鎖,server 0 次呼叫,擴充連呼叫事件都沒收到。觀察用擴充換掉結果,模型看到的是替換後的代號。兩個 server 的同名工具,omp 註冊成兩個名稱,各自送到各自的 server。

原始碼確認(omp 18.2.8): 每個 MCP 結果的細節欄位都帶著 server 的設定名稱與設定來源;擴充的結果 hook 收得到這些欄位,也能整段替換內容與細節。

圖二:同一個 MCP server,兩邊在三道門各看到什麼

https://ithelp.ithome.com.tw/upload/images/20261011/201835413oP5CanPJu.png

把三件事對一次:

三件事 Cursor IDE(他人實驗、公開報告、文件) omp 原生(實測) omp 加上結果守門員(實測)
看得到 沒有 server 啟動的 hook 事件;hook 收不到說明;呼叫後的 hook 知道 server 擴充讀得到說明;結果帶 server 名稱;啟動失敗只寫在紀錄檔 同左,每個結果另記一行
擋得住 呼叫前可依 server 拒絕;結果換得掉,卻分不出 server;設定檔的保護一再被繞過 --config 擋下專案設定檔;依工具名稱拒絕;預設不問 依 server 扣下結果,原文一起拿掉
查得到 呼叫後的 hook 記得到 server 與結果 名稱碰撞只留一行警告 帳本記下 server、工具、決定與字數

Cursor 的痛點在第三道門:知道 server 的改不了結果,改得了的不知道 server。omp 的痛點在第一道門,和 Cursor 一樣。下一節先補第三道門,再處理第一道。

三、補強 omp:Cursor 拆成兩支 hook 的事,omp 一支做完

omp 的結果 hook 同時拿得到結果細節裡的 server 名稱,以及替換結果的權力。新的結果守門員就用這一點:

  • 封鎖清單上的 server,或結果沒有 server 名稱: 扣下,模型只看到一則通知,細節欄位裡的原文一起換掉。
  • 命中注入句型: 不論哪台都扣下。句型沿用 Day25,再加上 Invariant Labs 公開過的寫法,如尖括號標出的 IMPORTANT、「不要告訴使用者」與指向金鑰的路徑。
  • 可信清單上的 server: 原樣放行;其他 server: 放行,但前面加一行標示,說這是工具回傳的資料,不是指令。
  • 帳本: 每個決定一行,記 server、工具、決定、原因、字數,不記內容;錯誤和沒有文字的結果原樣放行,記一行略過。

它認 server 只看細節欄位,不看工具名稱前綴:一台的前綴,可能正是另一台工具名稱的開頭(不呼叫模型的檢查,見附錄 B)。

Cursor 的痛點,在 omp 各這樣補:

Cursor IDE 的痛點(他人實驗、文件) omp 的補法 omp 的結果(實測)
知道 server 的 hook 改不了結果,改得了的不知道 server 守門員依細節欄位的 server 名稱決定 可信那台照常送到;封鎖那台的 23 個字元換成 243 個字元的通知;帳本兩行,各記一台
扣下之後,原文還留在紀錄裡 連細節欄位一起換掉 對話紀錄檔裡,被封鎖那個工具的原文 0 次,可信那個 2 次
惡意 repo 的設定檔一讀就跑(CurXecute、TrustFall) 用 --config 關掉專案層級的 MCP 設定 同一份 Cursor 設定檔,指令 0 次啟動;只寫在全域設定檔則照樣啟動
工具說明裡藏指令(Invariant Labs) 擴充在第一次請求前讀說明 讀得到;守門員不處理說明,這是限制
  1. 不信任的 repo,用 --config 關掉專案層級的 MCP 設定: 帶入 mcp.enableProjectConfig: false(實測:0 次啟動)。別只寫在全域設定檔,repo 的 .omp/config.yml 蓋得掉(實測)。
  2. 不要的工具逐一 deny: tools.approval 加上完整的工具名稱(實測:經由 xd:// 也擋得住),一樣從 --config 帶入。
  3. 要每次問,就別用預設模式: MCP 工具屬於寫入層級,預設和 write 模式都不會問;要問就加 --approval-mode always-ask。沒人看著時,需要核准的工具直接報錯(文件;Day28 用 bash 實測過)。

補強後,守門員那場兩台各被呼叫 1 次,模型看到一台原樣、一台通知;帳本記下哪一台、哪個工具、放行或扣下、原文多長。被 deny 擋下的呼叫,只有 omp 自己的事件串流記得到(實測)。

四、這些結果,還不能代表完整防護

守門員和設定補上了兩道門,但以下限制不能省略:

  • 設定檔仍然是可信輸入,兩邊都是。 omp 的文件直接這樣寫;Cursor 的修補守的是檔名與對話框。兩邊都沒有驗證要跑的指令是不是當初看過的那一個;omp 的設定是整個關掉專案層級,不是逐一核准。
  • 全域設定擋不住 repo。 repo 的 .omp/config.yml 排在全域設定之上,全域寫的 false 被它寫回 true,指令照樣啟動(實測);只有 --config 與執行時旗標排在它之上,核准設定也一樣(文件)。
  • 結果守門員在呼叫之後。 封鎖那台的結果被扣下了,但 server 紀錄顯示呼叫照樣送到(實測);那一次呼叫裡 server 做了什麼,守門員追不回來。
  • 工具說明沒有過濾,也沒有鎖定。 這一版守門員不處理說明;server 改了工具清單,omp 會重新綁定(文件),先正常、後變臉的手法對 omp 一樣成立。
  • 名稱碰撞,搶得到。 兩個設定名稱轉成同一個工具名稱時,omp 依原始名稱排序固定留一個,不會問你(原始碼確認);依工具名稱寫的 deny 或 allow,也就套到被留下的那台(文件)。OWASP 的建議是名稱模糊時直接擋下,並請使用者確認。
  • 句型對不上,認不出來。 換個說法的指令,守門員只會加標示,不會扣下(不呼叫模型的檢查);標示只是提醒,照不照做,仍然看模型。
  • 預設不問。 MCP 工具在 omp 屬於寫入層級,預設直接放行;Cursor 預設每次都問(文件)。這一點,Cursor 比較嚴。
  • Cursor 這一側沒有在這台機器實測。 引用的是別人在特定版本上的結果,修補後的行為可能不同;先前在這台機器上讓 Cursor 連上 MCP 沒有成功,那些結果不納入本篇。
  • 每種情境只跑一次。 模型這次沒有中餌、照實回報(實測),是單次觀察,不代表比例。

因此,這次能說的是:在列出的設定與情境下,omp 和 Cursor 一樣,會在模型開始之前就執行 repo 裡的 MCP 設定;omp 多了一個能整個關掉的設定(要從 --config 帶入),以及一支同時知道 server、又換得掉結果的 hook。 不是「裝了守門員,接上別人的 MCP 就安全了」。

五、實際使用時,先做哪些事?

使用 Cursor

  1. 打開不熟的 repo 前,先看專案的 MCP 設定檔:已啟用的 server 會在啟動時開啟(文件、他人實驗)。
  2. 更新到已修補的版本(公開報告)。
  3. 不要點訊息裡的 MCP 安裝連結:對話框不一定看得到完整指令(他人實驗);企業版用允許清單限制能跑的 server(文件)。
  4. 保留每次核准,展開參數再按(文件、他人實驗)。
  5. hook 只能在呼叫前依 server 擋:用 beforeMCPExecution 依 server 名稱拒絕,並設定失敗時擋下;依 server 處理結果,目前做不到(文件)。

使用 omp

  1. 不信任的 repo,用 --config 關掉專案層級的 MCP 設定,不要只寫在全域設定檔(實測);omp 也讀 Cursor、Claude Code、VS Code 的設定檔(文件)。
  2. 不用的 MCP 工具設成 deny(實測);要每次問,加 --approval-mode always-ask(文件)。
  3. 結果交給模型前,依 server 過一道守門員(實測)。
  4. server 名稱要分得開,定期看 omp 的行程紀錄檔:碰撞與啟動失敗只寫在那裡(實測)。

如果一份 MCP 設定需要人看過才能信,就不要讓 agent 在沒人看著的時候,替你打開那個 repo。

結語:設定要先關,結果要扣得下

Cursor 的 MCP 痛點,公開研究畫得很清楚:設定檔一讀就跑,守門的檔名與對話框一再被繞過;工具說明,模型看得到、人看不到;結果的 hook,知道 server 的改不了,改得了的不知道 server。

omp 的第一道門跟 Cursor 一樣守不住,但它補得上兩件事:從 --config 帶入的一個設定,把專案層級的 MCP 整個關掉;以及一支同時知道 server、又換得掉結果的 hook。

能做的,是三件事一起:不信任的設定先不讓它啟動,工具呼叫依名稱逐一拒絕,結果交給模型之前依 server 先看過。

今天看的是把別人的工具接進你的 agent。反過來,你的 agent 被開成別人的工具,別人送一句話進來就替你做事呢?Day28 接著看:對外發布,把自己的 agent 變成別人的工具。

自問自答

  • 問:omp 也會執行 repo 裡的 Cursor 設定檔,跟 TrustFall 有什麼不同? 同一類問題;omp 的無頭模式連信任提示都沒有(實測:0 次核准事件),但有一個設定能在啟動前整個關掉,前提是從 --config 帶入(實測)。
  • 問:守門員扣下了封鎖那台的結果,是不是代表那台 server 沒做什麼? 不是。server 紀錄顯示呼叫照樣送到(實測);守門員只決定模型看不看得到結果。
  • 問:已經用工具名稱設了 deny,為什麼還要管名稱碰撞? 規則綁的是名稱(文件);碰撞時 omp 只留一台,呼叫全送到被留下的那台(實測),規則也就管到那台,不一定是你想管的那台。

今天對應的威脅

T1——工具說明與回傳結果裡的間接注入;T3——別人寫的設定與工具在你的機器上執行、驅動你的 agent。 對應 OWASP 代理式應用十大風險的 ASI04「代理式供應鏈漏洞」(工具描述注入、相似名稱冒充)與 ASI05「非預期的程式執行」;結果裡的指令是 LLM01「提示注入」的間接型。

5 分鐘小練習

本練習不呼叫模型,也不修改你的工作區設定。以下路徑相對於 research_folder_omp_vs_Cursor/verification/day27/。

  1. 讀 runs/day27-summary.json:verdicts 每一項都是 holds: true,painPoints 與 sources 列出每個痛點的 omp 場次與 Cursor 來源。
  2. 打開 runs/O27-mcp-guard-per-server/guard-ledger.jsonl:兩行,d27-marker 放行、d27-marker-b 扣下,都沒有結果內容。
  3. 跑 bun mcp-result-guard-check.ts 與 bun summarize.ts --verify。重點是比較:守門員認 server 看細節欄位,不看工具名稱;換個說法的指令,它只會加標示。

附錄 A:測試條件與額外觀察

這次測了什麼?

  • 測試日期:2026-10-10,一台 Linux 機器,十種情境各跑一次,沒有重跑。Cursor 的文件與論壇於 2026-10-10 查閱,他人實驗依各自的公開日期。
  • omp:18.2.8,omp -p --mode json,模型 cursor-sdk/claude-opus-5-5,關閉 thinking;內建工具只開 read,疊加設定把 bash 與 eval 設為 deny;tools.xdev 維持預設(開)。每場用自己的暫存專案與 agent 目錄,跑完刪除。
  • MCP server:HTTP 版只綁 127.0.0.1,只接受同一個連接埠的 Host 與 Origin;stdio 版由 omp 依設定檔啟動,只寫自己的紀錄。工具說明、參數說明、server 說明、結果都是固定代號,不含任何指令。
  • 擴充依序以 -e 載入:cursor-sdk、(需要時)結果守門員、最後是觀察用擴充;觀察到的,就是守門員放行之後的內容。
  • 十種情境:專案設定檔自動啟動(預設;用 --config 關掉;全域設定檔關掉,但 repo 的 .omp/config.yml 寫回 true)、連不上的 server、觀察說明、依名稱 deny、替換結果、兩台同名工具、結果守門員(信任一台、封鎖一台)、名稱碰撞。
  • 判準:server 有沒有被啟動、被呼叫,看 server 自己的紀錄;模型看到什麼,看 omp 的事件串流與對話紀錄檔;不問 agent。
  • 清理:每場結束,server 行程 0 個殘留、暫存專案 0 個殘留;金鑰、email、家目錄絕對路徑的掃描都是 0。

四個不混入主結論的觀察

模型都經由 xd:// 呼叫 MCP。 六場需要呼叫的,模型全都用寫入工具寫到 xd://,沒有一場直接呼叫。第一場讓我們的解析程式漏算,修正後從原始紀錄重算,沒有重跑。

被擋的那場,模型照實說明。 它回覆呼叫被使用者政策封鎖,並寫出要怎麼放行;這是模型行為,判準是 server 的 0 次呼叫。

守門員那場,模型也照實回報。 它說第二次呼叫送出了,但結果被扣下,因為那台在封鎖清單上;這和 server 紀錄一致。

看不到送給模型的請求本文。 這次用的模型接入方式,不會觸發請求前的擴充事件;所以只能證明擴充在第一次請求前讀到說明,無法從請求本文確認說明一字不差地送進模型。

附錄 B:不呼叫模型的查證練習

本節供已取得本系列研究資料的讀者重現。以下路徑相對於 research_folder_omp_vs_Cursor/verification/day27/。

1. 對照關鍵場次

先讀 runs/day27-summary.json 的 verdicts 與 tally,再依這條順序看各場的 summary.json:

  • O27-mcp-project-autostart:projectConfigFiles 只有 .cursor/mcp.json;stdioServer.started 為 true,launchedBy 第一個是 omp;startedBeforeFirstModelRequest 為 true;approvalEvents 為 0。stdio-server-log.jsonl 是 server 自己的啟動、清單、結束紀錄。
  • O27-mcp-project-autostart-off:projectConfigOff 為 true;stdioServer.started 為 false,starts 為 0;registeredToolNames 為空。
  • O27-mcp-project-override:globalEnableProjectConfig 為 false、projectEnableProjectConfig 為 true,projectSettingsFiles 只有 .omp/config.yml;stdioServer.started 為 true,launchedBy 第一個是 omp。global-config.yml 與 project-config.yml 是當場寫入的兩份設定。
  • O27-mcp-startup-error:mcpLoadFailures.forServer 為 1;stdoutMentions 與 stderrMentions 都是 false;activeServerTools 為 0。
  • O27-mcp-observe:getAllTools.mcpTools[0] 的 desc 與 schema 為 true;extensionSawDescBeforeFirstModelRequest 為 true;beforeProviderRequestFired 為 false。reparsed 記下串流欄位重算前後的值。
  • O27-mcp-approval-deny:approvalKeySource 是從觀察那場讀到的名稱;errorText 寫著被使用者政策封鎖;deniedBeforeServer 為 true;toolCalls 為空。
  • O27-mcp-replace:modelFacingHasReplacedNotResult 為 true。
  • O27-mcp-two-servers:namesDistinct 為 true;serverCallLabels 有 a 與 b。
  • O27-mcp-guard-per-server:guard-ledger.jsonl 兩行;trustedResultReachedModel 與 blockedResultWithheld 為 true;blockedResultInSession 為 0;observerServers 列出擴充收到的 server 名稱。
  • O27-mcp-name-squat:registeredToolNames 只有一個;squatWinnerLabel 等於 expectedWinnerLabel(b,也就是 d27-marker);collisionLog 一行。

2. 重建彙總並確認

cd research_folder_omp_vs_Cursor/verification/day27
bun summarize.ts --verify
bun summarize.ts --scan

重點是比較:重建出來的彙總與存檔一致,十二個判定都成立;隱私掃描的金鑰、email、家目錄路徑都是 0。

3. 確認守門員與執行程式

cd research_folder_omp_vs_Cursor/verification/day27
bun mcp-result-guard-check.ts
bun run-omp-mcp.ts selftest
bun settings-precedence-check.ts

第一個把可信、封鎖、未知、命中句型、錯誤、沒有文字、沒有 server 名稱這幾種結果交給守門員,並確認用工具名稱前綴認 server 會認錯;第二個檢查十種情境的設定,以及 xd:// 呼叫的解析;兩者都不啟動 omp 的工作階段。第三個用 omp config get 問 omp 自己,在全域、專案、--config 三層各怎麼設時,mcp.enableProjectConfig 最後是多少;不連 MCP,也不呼叫模型。

4. 跑文章與圖的機械檢查

cd research_folder_omp_vs_Cursor/verification/day27
python3 article-check.py
node mermaid-check.mjs ../../day27-mcp.md

以上步驟不呼叫模型,也不修改你的工作區設定。場次說明見 runs/README.md;更早的內部紀錄不是本篇的證據,不在這裡列出。

附錄 C:來源

以下來源除另註日期者外,均為 2026-10-10 查閱的版本。產品行為可能隨版本更新,操作前應重新確認。

Cursor:他人實驗與公開報告

  • Aim Labs:CurXecute(2025-08-01,CVE-2025-54135):新的設定項目自動啟動;agent 建議的修改在使用者拒絕前已寫入;經由 Slack MCP 的提示注入觸發。CVE 說明為 1.3.9 以前受影響;研究者寫明修補在 1.3。
  • Check Point Research:MCPoison(2025-08-05,CVE-2025-54136):1.2.4 以前,核准綁在設定名稱;1.3 之後,任何變動都要重新核准。
  • Lakera:CVE-2025-59944(2025-10-10):1.6.23 以前,大小寫不同的路徑繞過敏感檔確認;1.7(2025-09-29)修補。
  • GHSA-6r98-6qcw-rxrw(2025-11-03):NTFS 短路徑與資料流語法繞過敏感檔偵測;1.7.44 受影響,2.0 修補。
  • GHSA-r22h-5wp2-2wfv(2025-08-01,CVE-2025-54133):安裝連結的對話框不顯示參數;1.3 修補。
  • GHSA-4575-fh42-7848(2025-11-03,CVE-2025-64106):安裝連結顯示假冒正牌 server 的對話框;2.0 修補。
  • Proofpoint:CursorJack(測試環境截至 2026-01-19):MCP 安裝連結可被用來執行指令,或安裝惡意的遠端 server;通報後以範圍外結案。
  • Adversa AI:TrustFall(2026-05-07):Cursor CLI 等四個 CLI,在接受資料夾信任後立刻啟動專案定義的 MCP server。
  • Adversa AI:DeepJack(2026-07-15):安裝對話框的單行欄位,可把指令後半段擠出畫面;發表時 3.9.8 仍受影響。
  • Invariant Labs:Tool Poisoning Attacks(2025-04-01):以 Cursor 為 client 的工具說明下毒、跨 server 影響可信工具,以及先正常、後變臉的工具說明;實驗程式碼。

Cursor:文件與論壇

omp

本次對照 omp 18.2.8 的原始碼與文件。以下路徑相對於 oh-my-pi-main/:

  • docs/mcp-config.md:會讀取的各工具設定檔(含 .cursor/mcp.json)、提交的 MCP 定義是可信輸入、mcp.enableProjectConfig。
  • docs/mcp-runtime-lifecycle.md:無頭模式在工作開始前完成 MCP 連線;收到工具清單變更通知就重新綁定。
  • docs/mcp-server-tool-authoring.md、packages/coding-agent/src/mcp/tool-bridge.ts:工具名稱的轉換規則;碰撞時依原始名稱排序留一個,並寫警告;結果細節帶 server 名稱與設定來源。
  • docs/approval-mode.md:MCP 工具屬於寫入層級;三種核准模式;tools.approval 依完整工具名稱設定。
  • docs/settings.md、packages/coding-agent/src/config/settings.ts:設定的優先序(全域 < 專案 < --config < 執行時旗標),以及專案層級設定的合併不排除任何鍵。
  • docs/hooks.md、packages/coding-agent/src/extensibility/extensions/wrapper.ts:結果 hook 可替換內容與細節。
  • packages/coding-agent/src/tools/xdev.ts、docs/tools/write.md:xd:// 虛擬工具,以及只轉送、不寫檔的寫入。
  • packages/coding-agent/src/config/settings-schema.ts:mcp.enableProjectConfig、tools.xdev 的預設值與介面說明。

上述位置是研究版本的查證索引,不代表新版檔案位置或行為不會改變。

安全框架

  • OWASP Top 10 for Agentic Applications 2026(完整文件):ASI04「Agentic Supply Chain Vulnerabilities」常見例子中的工具描述注入與相似名稱冒充;ASI05「Unexpected Code Execution」;ASI02 的緩解建議第 7 條:使用完整的工具名稱,名稱模糊時直接擋下,並請使用者確認。

上一篇
agent 用瀏覽器讀到的網頁,hook 看得到卻扣不下
下一篇
把 agent 交給別人的程式:動作生效前,誰能喊停?
系列文
一個 Agent 我查不動,一個我改得動:內部威脅偵測的 30 天 共 28 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言