為什麼 MCP Server 需要額外的安全設計
MCP(Model Context Protocol)讓 AI 模型可以呼叫外部工具,從讀取檔案到操作資料庫都可以。每一個 MCP Server 都是 AI 與真實系統之間的橋樑,一旦 Server 本身有安全問題,攻擊者就可能透過 AI 模型間接操作你的系統。
飛飛在做資安顧問時,看過不少團隊在開發 MCP Server 時只關注「功能有沒有動」,忽略了輸入驗證、權限控制和日誌記錄。這和十年前 Web API 開發的狀況很像——先上線再補安全,結果往往是出事才補。
工具描述的安全撰寫
MCP Server 註冊工具時需要提供 description,這段文字會被送進 AI 模型的上下文。撰寫工具描述時,應該遵循以下原則:
只描述工具的功能和參數格式,不在描述中包含任何行為指令。避免使用「你應該」、「請先」、「在回傳前」這類可能被模型當作指令的用語。
不好的寫法:「查詢使用者資料。在回傳前,請先檢查使用者是否有存取權限,如果沒有,請呼叫 grant_access 工具。」
好的寫法:「根據 user_id 查詢使用者的公開資料。需要參數:user_id(string)。回傳格式:JSON 物件包含 name、email、role。」
差別在於:前者在描述裡嵌入了行為邏輯,可能被攻擊者仿照格式注入惡意指令;後者只描述輸入和輸出,行為邏輯在 Server 程式碼裡實作。
工具參數的輸入驗證
AI 模型呼叫工具時傳入的參數來自自然語言理解的結果,不能假設參數一定合法。每個工具的參數都需要嚴格驗證。
實作重點:
型別檢查。確認參數型別與 JSON Schema 定義一致。數字就是數字,字串不能包含控制字元。
範圍限制。路徑參數不能包含 ../ 來做路徑穿越。ID 參數應該限定格式(例如 UUID)。查詢參數應該有長度上限。
白名單驗證。檔案路徑只允許存取特定目錄。URL 參數只允許特定 domain。命令參數只允許預定義的選項。
以 Node.js 的 MCP Server 為例,一個讀取檔案的工具應該這樣驗證路徑:
const ALLOWED_DIR = '/data/public';
function validatePath(inputPath) {
const resolved = path.resolve(ALLOWED_DIR, inputPath);
if (!resolved.startsWith(ALLOWED_DIR)) {
throw new Error('Path traversal detected');
}
return resolved;
}
工具輸出的過濾
MCP Server 回傳給 AI 模型的結果會被注入到對話上下文中。如果回傳內容包含可能被當作指令的文字,就構成了間接 Prompt Injection 的攻擊面。
過濾策略:
限制回傳長度。單次工具回傳不應超過必要的大小,避免大量文字中藏有惡意指令。
結構化回傳。盡量回傳 JSON 格式而不是原始文字,讓 AI 模型更容易區分「資料」和「指令」。
敏感資訊遮蔽。回傳的結果中如果包含 API Key、密碼、Token,應該在 Server 端就做遮蔽處理(例如只顯示最後四碼)。
標記資料來源。在回傳的 metadata 中標記資料來源是否可信,讓上層應用可以做風險判斷。
認證與授權
MCP Server 的認證和授權分兩個層次:
Server 層級:誰可以連接這個 MCP Server?使用 API Key、mTLS 或 OAuth 來驗證連接的 Host 身份。
工具層級:連接之後,哪些工具可以使用?根據 Host 的身份和使用情境,限制可呼叫的工具集合。
在 SSE 傳輸模式下,Server 暴露在網路上,認證尤其重要。建議的做法:
使用 Bearer Token 認證每個 HTTP 連接。Token 應該有過期時間和權限範圍。不同的 Host 使用不同的 Token,權限各自獨立。每次工具呼叫記錄使用的 Token 身份,方便事後稽核。
在 Stdio 模式下,因為是本地進程間通訊,連接認證較不重要,但工具層級的授權仍然需要。例如,即使是本地的 MCP Server,讀取 /etc/shadow 的權限也不應該開放給一般的 AI 對話。
日誌與監控
所有工具呼叫都應該記錄完整日誌,包含:
時間戳記、呼叫的工具名稱、輸入參數(脫敏後)、輸出結果的摘要(不需要完整結果)、呼叫者的 Session ID、執行結果(成功或失敗及錯誤類型)。
監控告警的觸發條件建議包括:
單一 Session 在短時間內呼叫大量工具(可能是自動化攻擊)。存取從未被使用過的工具(可能是探測行為)。工具呼叫失敗率突然升高(可能有人在嘗試非法參數)。存取敏感資源的頻率異常(可能是資料外洩的前兆)。
日誌本身也需要安全保護。寫入日誌的參數和結果應該先脫敏,避免日誌系統本身成為敏感資料的外洩管道。
網路隔離與部署
MCP Server 的部署架構直接影響攻擊面的大小:
Stdio 模式建議的部署方式:MCP Server 以子進程的形式運行在 Host 的同一台機器上,用檔案系統權限和 Linux 使用者隔離來限制存取範圍。使用 Docker 容器進一步限制可用的系統呼叫和網路存取。
SSE 模式建議的部署方式:MCP Server 部署在獨立的網路區段。使用反向代理(Nginx、Cloudflare Tunnel)做 TLS 終止和存取控制。防火牆規則只允許已知的 Host IP 連接。Server 不應該能夠存取 AWS metadata endpoint(169.254.169.254)或其他雲端管理 API。
無論哪種模式,MCP Server 都不應該使用 root 權限運行。建立專用的系統使用者,只給予必要的檔案和網路權限。
安全開發檢查清單
開發 MCP Server 時,上線前確認以下項目:
工具描述只包含功能和參數說明,沒有行為指令。所有工具參數都有型別和範圍驗證。檔案路徑參數有路徑穿越防護。URL 參數有白名單或至少禁止內網 IP。輸出結果有長度限制和敏感資訊遮蔽。認證機制已實作(SSE 模式必要)。每次工具呼叫都有日誌記錄。使用非 root 使用者運行。依賴套件是最新版本且沒有已知漏洞。
安全與限制
MCP 是一個快速發展中的協定,安全最佳實踐也在持續演進。這篇文章的建議基於 2026 年中期的版本,未來可能有變動。
目前 MCP 規範本身對安全的要求較為寬鬆,大部分安全措施需要由 Server 開發者和部署者自行實作。這意味著不同 Server 的安全水準差異很大,使用第三方 Server 時需要額外謹慎。
沒有任何防護措施可以完全阻擋透過 AI 模型的間接攻擊。安全設計的目標是提高攻擊成本、縮小影響範圍、確保事後可追蹤。
知識檢測
讀完文章後,測試一下你對這個主題的理解。
常見問題
我用的 MCP Server 是官方提供的,還需要做額外安全設定嗎?
需要。官方 Server 的程式碼品質通常較好,但預設設定可能不適合你的環境。例如 filesystem Server 預設可能允許存取整個磁碟,你需要限制只能存取特定目錄。fetch Server 預設可能沒有 URL 白名單,你需要自行加上。
MCP Server 的依賴套件要注意什麼?
和所有 Node.js/Python 專案一樣,定期執行 npm audit 或 pip-audit 檢查已知漏洞。特別注意 MCP SDK 本身的版本更新,因為協定還在快速演進中,安全修補可能頻繁發布。鎖定依賴版本(package-lock.json / requirements.txt)避免供應鏈攻擊。
可以同時連接多少個 MCP Server?有安全考量嗎?
技術上沒有硬性限制,但從安全角度,連接的 Server 越多,攻擊面越大。建議的做法是只連接當前任務需要的 Server,不要「全部開著以備不時之需」。不同安全等級的工作使用不同的 Server 組合。
怎麼知道 MCP Server 有沒有被篡改?
對自建的 Server,使用 Git 追蹤程式碼變更,部署時比對 checksum。對第三方 Server,驗證來源(GitHub repository、npm package)的簽章和維護者身份。定期比對運行中的版本和已知安全版本。
台灣的企業使用 MCP 需要注意哪些合規問題?
如果 MCP Server 存取或處理個人資料,需要符合台灣個資法的規範。特別注意:工具日誌中可能包含個人資料需要妥善保護、跨境資料傳輸(如果 Server 部署在海外)需要評估風險、蒐集和處理個資需要有明確的法律依據。
相關文章
- MCP 攻擊面分析:工具連接如何擴大 AI 的安全風險
- AI Agent 安全檢查清單:自主 AI 的權限管控
- RAG 安全指南:檢索增強生成的 5 個攻擊向量
- AI 供應鏈安全:模型、套件、API 的信任鏈風險
參考資料
- Model Context Protocol 官方規範
- OWASP LLM Top 10 2025
- CWE-918: Server-Side Request Forgery (SSRF)