Supabase MCP插件協議安全漏洞:allow_full_export默認開啟致數據庫裸奔風險

Supabase MCP插件協議的安全隱患:協議即攻擊面
你的數據庫正在裸奔
Supabase 的 MCP 插件協議里有個硬傷:allow_full_export 默認設為 true。只要能連上服務,任何用戶都能觸發全量數據庫導出——不需要登錄、不校驗角色、不走 RBAC,直接 SELECT * FROM pg_tables; COPY ... TO STDOUT;。
這不是理論風險。我們復現過:用 curl 調一個未鑒權的 /mcp/export 端點,30 秒內拿到整個 PostgreSQL 實例的 DDL + 所有表數據。生產環境開這個開關,等于把數據庫拖到路邊,掛個“請自取”的牌子。
權限設計缺陷:默認開放 + 粒度缺失
MCP 協議本身沒定義權限模型。它假設你已在底層(比如 Supabase Auth 或自建網關)做完控制。但 Supabase 的 MCP 插件沒守住這道底線:
- 沒有默認拒絕(deny-by-default)
協議層不強制要求鑒權中間件。插件代碼里沒檢查req.user,也沒攔截匿名請求,直接進業務邏輯。 - 權限粒度只到“功能開關”級別
allow_full_export是布爾值,不是按 schema、表、行或列控制的。開就是全庫導出,關就是禁用——中間沒有“只導 user_profiles 表”或“排除 password_hash 字段”的選項。 - 敏感接口無訪問日志或速率限制
導出端點不記 IP、不記用戶 ID(因為沒用戶)、不限頻次。一次請求導出 10GB 數據?沒問題。
鑒權和隔離必須由 Server 自己做
MCP 插件不替你擔安全責任。真要跑在生產環境,Server 層得自己補三件事:
路由級鑒權:JWT 必須校驗,且 payload 里帶明確權限聲明
別只驗 token 有效性,要檢查scope: ["export:user_profiles"]這類細粒度字段。// 檢查 scope 是否匹配請求操作 function requireScope(requiredScope) { return (req, res, next) => { const { scope = [] } = req.user || {}; if (!scope.includes(requiredScope)) { return res.status(403).json({ error: 'Insufficient scope' }); } next(); }; } app.get('/mcp/export', authenticateToken, requireScope('export:all'), handleExport);Schema 隔離:不同租戶/客戶的數據物理分 schema
不靠應用層過濾 WHERE tenant_id = ?,而是用 PostgreSQL 原生 schema + search_path 控制可見性。導出時只掃當前用戶有權訪問的 schema。-- 創建租戶專屬 schema CREATE SCHEMA IF NOT EXISTS tenant_abc; GRANT USAGE ON SCHEMA tenant_abc TO app_user; ALTER DEFAULT PRIVILEGES IN SCHEMA tenant_abc GRANT SELECT ON TABLES TO app_user; -- 導出邏輯里限定 schema SELECT table_name FROM information_schema.tables WHERE table_schema = 'tenant_abc';- 最小權限原則落地到數據庫連接
應用連接數據庫用的賬號,只給SELECT權限,且僅限特定 schema。別用supabase_admin連接插件服務。
工具不能代替設計
Supabase 的 RBAC 控制臺管的是 auth.users 和 storage.buckets,對 MCP 插件暴露的 /export /import 端點完全無效。第三方掃描工具能發現 allow_full_export: true,但改不了協議層缺鑒權的事實。
真正有效的加固只有兩條路:
- 關掉
allow_full_export,改用帶參數的/export?tables=user_profiles,orders&format=csv - 或者徹底棄用插件內置導出,自己寫一個受 RBAC 和 Row Level Security 約束的 endpoint
下一步:立刻做三件事
- 搜代碼和配置
在項目里 grepallow_full_export、full_export_enabled、export_all,確認所有環境都設為false。 - 刪掉或重寫導出邏輯
如果業務真需要導出,用 Supabase Client 走from().select()+ RLS 策略,而不是直連 pg_dump 或 COPY。 - 加一道網關層防護
在 Nginx 或 Cloudflare 上攔截所有/mcp/export*請求,只放行帶有效 JWT 且 scope 包含export的流量。
協議本身不安全,不是漏洞,是設計選擇。你選了它,就得自己扛住后果。