
supabase
热门在执行任何涉及 Supabase 的任务时使用。触发条件:Supabase 产品(数据库、认证、边缘函数、实时功能、存储、向量、定时任务、队列);客户端库和 SSR 集成(supabase-js、@supabase/ssr)在 Next.js、React、SvelteKit、Astro、Remix 中;认证问题(登录、登出、会话、JWT、Cookie、getSession、getUser、getClaims、RLS);Supabase CLI 或 MCP 服务器;模式变更、迁移、安全审计、Postgres 扩展(pg_graphql、pg_cron、pg_vector)。
在执行任何涉及 Supabase 的任务时使用。触发条件:Supabase 产品(数据库、认证、边缘函数、实时功能、存储、向量、定时任务、队列);客户端库和 SSR 集成(supabase-js、@supabase/ssr)在 Next.js、React、SvelteKit、Astro、Remix 中;认证问题(登录、登出、会话、JWT、Cookie、getSession、getUser、getClaims、RLS);Supabase CLI 或 MCP 服务器;模式变更、迁移、安全审计、Postgres 扩展(pg_graphql、pg_cron、pg_vector)。
Supabase
核心原则
1. Supabase 频繁变更——在实施前请对照更新日志和当前文档进行验证。
不要依赖训练数据中的 Supabase 功能。函数签名、config.toml 设置和 API 约定在不同版本间会发生变化。
首先,获取 https://supabase.com/changelog.md(一个轻量级的摘要索引——不是繁重的拉取),扫描与你的任务相关的 breaking-change 标签,并按照链接页面处理任何适用的变更。然后使用下面的文档访问方法查找相关主题。
2. 验证你的工作。
在实施任何修复后,运行一个测试查询以确认更改生效。未经验证的修复是不完整的。
3. 从错误中恢复,不要循环。
如果一种方法在尝试 2-3 次后失败,停下来重新考虑。尝试不同的方法,检查文档,更仔细地检查错误,并在可用时查看相关日志。Supabase 的问题并不总是通过重试相同命令来解决,答案也不总是在日志中,但在继续之前,日志通常值得检查。
4. 将表暴露给数据 API: 根据用户的数据 API 设置,新创建的表可能不会自动通过数据(REST)API 暴露。如果是这种情况,需要显式授予 anon 和 authenticated 角色访问权限。
注意,这与 RLS 不同,RLS 控制的是表可访问后哪些_行_可见,而不是表是否可访问。
当用户报告 SQL 创建的表意外不可访问时,检查他们的数据 API 设置以及是否通过显式的 GRANT SQL 授予了角色访问权限。在授予公共(anon/authenticated)访问权限时,始终启用 RLS。有关完整设置工作流程,请参见将表暴露给数据 API。
5. 暴露模式中的 RLS。
在任何暴露模式(默认包括 public)的每个表上启用 RLS。这在 Supabase 中至关重要,因为暴露模式中的表在 anon/authenticated 角色具有访问权限时,可以通过数据 API 访问(参见将表暴露给数据 API)。对于私有模式,建议使用 RLS 作为纵深防御。启用 RLS 后,创建与实际访问模型匹配的策略,而不是默认每个表都使用相同的 auth.uid() 模式。
6. 安全检查清单。
在处理任何涉及认证、RLS、视图、存储或用户数据的 Supabase 任务时,请运行此清单。这些是 Supabase 特有的安全陷阱,会静默地创建漏洞:
-
认证和会话安全
- 切勿在基于 JWT 的授权决策中使用
user_metadata声明。 在 Supabase 中,raw_user_meta_data是用户可编辑的,并且可能出现在auth.jwt()中,因此对于 RLS 策略或任何其他授权逻辑来说是不安全的。请改用raw_app_meta_data/app_metadata存储授权数据。 - 删除用户不会使现有的访问令牌失效。 首先登出或撤销会话,对于敏感应用保持 JWT 过期时间短,并且为了严格保证,在敏感操作中根据
auth.sessions验证session_id。 - 如果你使用
app_metadata或auth.jwt()进行授权,请记住 JWT 声明在用户令牌刷新之前并不总是最新的。
- 切勿在基于 JWT 的授权决策中使用
-
API 密钥和客户端暴露
- 切勿在公共客户端中暴露
service_role或密钥。 在前端代码中优先使用可发布的密钥。旧版anon密钥仅用于兼容性。在 Next.js 中,任何NEXT_PUBLIC_环境变量都会发送到浏览器。
- 切勿在公共客户端中暴露
-
RLS、视图和特权数据库代码
- 视图默认绕过 RLS。 在 Postgres 15 及以上版本中,使用
CREATE VIEW ... WITH (security_invoker = true)。在旧版本的 Postgres 中,通过撤销anon和authenticated角色的访问权限,或将视图放在未暴露的模式中来保护视图。 - UPDATE 需要 SELECT 策略。 在 Postgres RLS 中,UPDATE 需要先 SELECT 该行。如果没有 SELECT 策略,更新会静默返回 0 行——没有错误,只是没有变化。
auth.role()已弃用——请改用TO子句。 Supabase 已弃用auth.role(),转而直接在策略上使用TO authenticated或TO anon指定目标角色。除了弃用之外,auth.role() = 'authenticated'在启用匿名登录时会静默失效,因为匿名用户携带authenticatedPostgres 角色,无论用户是否真正登录,都会通过检查。-- 已弃用(请勿使用) create policy "example" on table_name for select using ( auth.role() = 'authenticated' );- 仅使用
TO authenticated是认证而非授权(BOLA / IDOR)。 仅使用TO authenticated只检查角色——它不限制用户可以访问哪些行。正确的模式是将TO authenticated与USING中的所有权谓词结合:create policy "example" on table_name for select to authenticated using ( (select auth.uid()) = user_id ); - UPDATE 策略需要同时包含
USING和WITH CHECK。 如果没有WITH CHECK,用户可以将行的user_id重新分配给另一个用户:create policy "example" on table_name for update to authenticated using ( (select auth.uid()) = user_id ) with check ( (select auth.uid()) = user_id ); SECURITY DEFINER函数会绕过 RLS。SECURITY DEFINER函数以其创建者的权限运行——通常是具有bypassrls的角色(例如postgres)。切勿添加SECURITY DEFINER来解决权限错误;它会静默地移除访问控制而不修复根本原因。请优先使用SECURITY INVOKER。public中的SECURITY DEFINER函数可被所有角色调用。 Postgres 默认对每个新函数授予PUBLIC的EXECUTE权限,因此public中的任何SECURITY DEFINER函数都是一个公共 API 端点,可由anon和authenticated(继承自PUBLIC)调用,无需任何额外授权。当确实需要SECURITY DEFINER时(例如,绕过内部查找表上的 RLS),将函数放在未暴露的模式中,始终在函数体内包含auth.uid()检查,并在更改后运行supabase db advisors。
- 视图默认绕过 RLS。 在 Postgres 15 及以上版本中,使用
-
存储访问控制
- 存储的 upsert 需要 INSERT + SELECT + UPDATE。 仅授予 INSERT 允许新上传,但文件替换(upsert)会静默失败。你需要所有三个权限。
-
依赖和供应链安全
- 在安装 Supabase 包(
supabase-js、@supabase/ssr、supabase-py等)时,始终固定包版本并提交锁定文件。 有关完整清单,请参见 npm 安全指南。
- 在安装 Supabase 包(
对于上述未涵盖的任何安全问题,请获取 Supabase 产品安全索引:https://supabase.com/docs/guides/security/product-security.md
Supabase CLI
始终通过 --help 发现命令——切勿猜测。CLI 结构在不同版本间会发生变化。
supabase --help # 所有顶级命令
supabase <group> --help # 子命令(例如 supabase db --help)
supabase <group> <command> --help # 特定命令的标志
Supabase CLI 已知陷阱:
supabase db query需要 CLI v2.79.0+ → 使用 MCPexecute_sql或psql作为后备supabase db advisors需要 CLI v2.81.3+ → 使用 MCPget_advisors作为后备- 当你需要新的迁移 SQL 文件时,始终先使用
supabase migration new <name>创建它。切勿自行发明迁移文件名或依赖记忆中的预期格式。
版本检查和升级: 运行 supabase --version 检查。有关 CLI 更新日志和版本特定功能,请查阅 CLI 文档 或 GitHub 发布。
Supabase MCP 服务器
有关设置说明、服务器 URL 和配置,请参见 MCP 设置指南。
连接问题排查——按顺序执行以下步骤:
-
检查服务器是否可达:
curl -so /dev/null -w "%{http_code}" https://mcp.supabase.com/mcp
返回401是预期的(无令牌),表示服务器正在运行。超时或“连接被拒绝”表示服务器可能已关闭。 -
检查
.mcp.json配置:
验证项目根目录是否存在有效的.mcp.json,其中包含正确的服务器 URL。如果缺失,请创建一个指向https://mcp.supabase.com/mcp的文件。 -
认证 MCP 服务器:
如果服务器可达且.mcp.json正确,但工具不可见,则用户需要进行认证。Supabase MCP 服务器使用 OAuth 2.1——告诉用户在其代理中触发认证流程,在浏览器中完成,然后重新加载会话。
Supabase 文档
在实施任何 Supabase 功能之前,请找到相关文档。按优先级顺序使用以下方法:
- MCP
search_docs工具(首选——直接返回相关片段) - 以 Markdown 形式获取文档页面——任何文档页面都可以通过在 URL 路径后附加
.md来获取。 - 针对 Supabase 特定主题进行网络搜索,当你不知道应该查看哪个页面时。
创建和提交模式变更
要进行模式变更,请使用 execute_sql(MCP)或 supabase db query(CLI)。 这些命令直接在数据库上运行 SQL,而不创建迁移历史记录,因此你可以自由迭代,并在准备好时生成干净的迁移。
不要使用 apply_migration 来更改本地数据库模式——它每次调用都会写入迁移历史记录,这意味着你无法迭代,并且 supabase db diff / supabase db pull 会产生空或冲突的差异。如果你使用它,你将受限于第一次尝试时传递的任何 SQL。
准备好提交你的更改到迁移文件时:
- 运行顾问 →
supabase db advisors(CLI v2.81.3+)或 MCPget_advisors。修复任何问题。 - 如果更改涉及视图、函数、触发器或存储,请检查上面的安全检查清单。
- 生成迁移 →
supabase db pull <descriptive-name> --local --yes - 验证 →
supabase migration list --local
参考指南
- 技能反馈 → references/skill-feedback.md
当用户报告此技能提供了错误指导或缺少信息时,必须阅读。





