一個標示為「唯讀」的資料庫工具,為何可能一路變成作業系統命令執行入口?關鍵不在於 MCP 協定本身,而在於應用程式如何解讀「唯讀」,以及 PostgreSQL 帳號最後究竟握有多少權限。
事件背景:修補早於公開警報
原始分析指出,AWS Labs 的 postgres-mcp-server 在預設唯讀模式下,曾未攔住 COPY ... TO PROGRAM。攻擊者若把特製 SQL 植入代理會讀取的內容,經由已驗證使用者觸發工具呼叫,便可能讓 SQL 抵達資料庫。原文與技術脈絡見:https://dev.to/kielltampubolon/read-only-postgres-mcp-servers-fail-with-1-sql-keyword-18b8。
可確認的來源事實是:AWS 於 2026 年 9 月 9 日公布 CVE-2026-87911;受影響版本為 1.1.7 以前,GitHub 公告給予 CVSS 3.1 的 9.6 分。成立條件包括使用 PG wire 連線、自行管理的 PostgreSQL,以及 MCP 連線角色具備超級使用者或 pg_execute_server_program 權限。1.1.7 已修補此問題:https://aws.amazon.com/security/security-bulletins/2026-104-aws/、https://github.com/awslabs/mcp/security/advisories/GHSA-fph8-pg5w-78fv。
PyPI 紀錄顯示,1.1.7 其實早在 6 月 25 日上架,距公告超過兩個月。這段落差的實際意義是:使用浮動最新版者可能早已被動取得修補,鎖定舊版、內嵌原始碼或維護 fork 的團隊,卻未必知道應立刻處理。版本資料見:https://pypi.org/project/awslabs.postgres-mcp-server/1.1.7/。
一個關鍵字如何穿過「唯讀」
COPY 不只是匯入、匯出表格資料。搭配 PROGRAM 時,PostgreSQL 伺服器會直接執行指定程式,命令不是跑在使用者電腦,也不是跑在 MCP 客戶端,而是在資料庫主機上,並繼承 PostgreSQL 作業系統帳號能觸及的資源。官方文件同時明定,這項能力只應開放給超級使用者或持有 pg_execute_server_program 的角色:https://www.postgresql.org/docs/current/sql-copy.html。
這也解釋了為何把交易設成 READ ONLY 並不足夠。PostgreSQL 的唯讀交易會禁止寫入一般資料表的 INSERT、UPDATE、DELETE 與 COPY FROM 等操作,但官方明確稱這只是「高階層的唯讀概念」,無法阻止所有磁碟寫入;禁止清單也未包含 COPY TO PROGRAM。交易模式約束資料操作,角色權限才約束能否叫資料庫主機執行程式:https://www.postgresql.org/docs/current/sql-set-transaction.html。
為何現在值得注意
合理推論是:這起事件揭露的不是單一關鍵字有多神奇,而是 AI 代理把外部內容、使用者身分與高權限工具串成同一條執行鏈。攻擊者未必需要登入資料庫;他只要影響模型讀到的文字,再由代理代為提出查詢。CVSS 中「不需攻擊者權限、但需要使用者互動」正反映這種間接路徑。
更值得警惕的是安全邊界放錯位置。舊版用阻擋清單識別危險語法,能攔住已知名稱,卻很難窮舉 PostgreSQL 擴充功能、自訂函式、動態 SQL 與未來新增能力。9 月初另一項 CVE-2026-85787 也涉及 1.1.7 以前版本的唯讀檢查不完整,說明「再補一個名稱」並非穩定的權限模型。
影響範圍與容易忽略的限制
不能把此漏洞簡化成「所有 Postgres MCP 都能拿 shell」。AWS 公告限定於特定舊版、PG wire、自管 PostgreSQL與高權限角色;若 MCP 使用專屬低權限角色,資料庫會直接拒絕 COPY ... PROGRAM。同樣地,CVSS 9.6 描述的是條件成立時的技術衝擊,不等於每個部署都有同樣風險。
截至 10 月初,專案現行文件顯示查詢已改以 PostgreSQL 解析器處理,會拒絕多陳述句、解析錯誤、命令執行與主機檔案操作;但維護者仍把這層稱為「最佳努力」的縱深防禦,並承認解析器無法看穿任意第三方函式或動態 SQL。這項更新降低已知繞過空間,並沒有把應用層驗證升格成真正的權限邊界:https://github.com/awslabs/mcp/blob/main/src/postgres-mcp-server/README.md。
對台灣企業的實際意義
作者觀點是:企業導入 MCP 時,不應把產品介面的「唯讀」標籤直接寫進風險評估結論。金融、製造、醫療與零售常把代理接上內部報表庫;一旦沿用管理員帳號求快速上線,原本只是資料查詢的元件,就可能取得讀取主機檔案、跨網路存取或執行程式的能力。真正可稽核的問題應是:「資料庫拒絕什麼?」而不是「MCP 宣稱攔截什麼?」
- 盤點實際套件、容器映像與 fork,確認不是只更新部署文件,而是執行中的版本已至少包含 1.1.7 修補。
- 為每個代理建立專屬角色,只授予必要資料庫的
CONNECT、必要 schema 的USAGE與指定資料表的SELECT。 - 確認角色不是超級使用者,也未繼承
pg_execute_server_program、pg_read_server_files或pg_write_server_files。 - 把資料庫程序放入受限主機或容器,限制對外連線、檔案系統與雲端中繼資料服務;這是降低失守後衝擊,不是取代資料庫權限。
後續觀察指標
接下來應觀察三件事:維護者是否把高權限角色檢查變成預設啟動門檻;企業是否能在稽核紀錄中區分使用者、模型與工具實際送出的 SQL;以及後續安全公告是否仍反覆出現「遺漏一個函式或語法節點」。若同類漏洞持續發生,答案就很清楚:MCP 的唯讀過濾適合改善操作體驗,真正的安全承諾仍必須落在資料庫角色、主機隔離與可追溯的授權鏈上。