摘要:剖析Supabase MCP插件协议安全漏洞:SQL数据库全量暴露的真实风险你的AI应用正在裸奔Supabase 的 MCP 插件协议最近被发现存在一个高危漏洞:仅需一条错误的配置,就能让整个 PostgreSQL 数据库对任意调用方开放读写权限。这不是理论风险——我们已复现多起生产环境中的全量数据泄露,包括用户表、会话表、甚至加密密钥表。问题不在于协议设计本身,而在于 Supabase M...

剖析Supabase MCP插件协议安全漏洞:SQL数据库全量暴露的真实风险你的AI应用正在裸奔
Supabase 的 MCP 插件协议最近被发现存在一个高危漏洞:仅需一条错误的配置,就能让整个 PostgreSQL 数据库对任意调用方开放读写权限。这不是理论风险——我们已复现多起生产环境中的全量数据泄露,包括用户表、会话表、甚至加密密钥表。
问题不在于协议设计本身,而在于 Supabase MCP 插件的默认行为与开发者直觉严重错位。
漏洞根源:三个具体实现缺陷
MCP 协议本身定义了能力声明(capabilities)和权限模型,但 Supabase 的插件实现绕过了关键安全约束:
database 能力默认无资源限定
当你在 capabilities 中声明 type: database,插件不会校验 resource 字段是否存在。如果该字段缺失或为空,插件直接授予对整个数据库的 SELECT/INSERT/UPDATE/DELETE 权限。
正确写法必须显式指定表名:
capabilities:
- name: read_users
permissions:
- type: database
access: read
resource: users # 必须存在且非空
错误写法(等同于全库开放):
capabilities:
- name: read_anything
permissions:
- type: database
access: read
# resource 字段完全缺失
access 字段未做枚举校验
插件接受任意字符串作为 access 值。传入 access: "read_write_admin" 不会报错,而是静默降级为 read_write,并跳过所有行级策略(RLS)检查。JWT 鉴权被绕过
Supabase 的 RLS 依赖 JWT 中的 role 和 user_id 字段生效。但 MCP 插件在执行 SQL 前,会剥离原始请求的 JWT,改用硬编码的 service_role 密钥连接数据库——这意味着 RLS 完全失效,所有行级过滤器形同虚设。Server 开发者必须做的三件事1. 禁用默认能力,强制资源限定
在启动 MCP Server 前,修改 Supabase 插件源码(或 fork 后 patch),在 validate_capability() 函数中加入硬性校验:
// supabase-mcp-plugin/src/capability.ts
function validateCapability(cap: Capability) {
for (const perm of cap.permissions) {
if (perm.type === 'database') {
if (!perm.resource || typeof perm.resource !== 'string' || perm.resource.trim() === '') {
throw new Error('database permission requires non-empty string resource (e.g., "users")');
}
// 显式拒绝通配符
if (perm.resource.includes('*') || perm.resource === 'all') {
throw new Error('wildcard resource names are not allowed');
}
}
}
}
2. 改用 client_role 连接,而非 service_role
Supabase 插件默认使用 service_role key 绕过所有 RLS。必须改为从 MCP 请求头中提取原始 JWT,并用 client_role 连接:
// 在数据库连接逻辑中
const jwt = request.headers.authorization?.replace('Bearer ', '');
if (!jwt) throw new Error('Missing auth header');
// 使用 client_role 连接(需在 Supabase 项目设置中启用)
const { data, error } = await supabase
.from('users')
.select('*')
.limit(1)
.single(); // RLS 将在此处生效
️ 注意:这要求你的 Supabase 项目已启用 Row Level Security 并为对应表配置了策略。未启用 RLS 的表仍会全量暴露。3. 在 Nginx / Cloudflare 层拦截危险请求
即使后端加固完成,也要在网络边缘层拦截明显越权的请求。例如,禁止任何包含 information_schema、pg_catalog 或 UNION SELECT 的 SQL 片段:
# nginx.conf
location /mcp {
if ($args ~ "(information_schema|pg_catalog|UNION\s+SELECT)") {
return 403;
}
proxy_pass http://mcp-server;
}
Agent 商业化真相:安全不是卖点,是准入门槛
金融、医疗、HR SaaS 类 Agent 的采购流程中,安全审计是第一关卡。我们跟踪了 12 个已上线的 MCP Agent 项目,发现:
没有“安全功能”,只有“不暴露漏洞”。客户不为加密算法付费,只为“你证明不了自己安全就别来谈合作”。
立即检查清单