你用 AI 开发的应用在泄露数据吗?10 分钟完成 Supabase 自查
用 Lovable 或 Bolt 基于 Supabase 开发的应用,经常带着任何人都能读取的数据表上线。本文介绍如何在十分钟内自查,以及应该先修复什么。
阅读约 4 分钟
用 Lovable、Bolt 或类似工具开发的应用,通常把数据存放在 Supabase 中。这是个不错的选择:Supabase 是一个真正的 Postgres 数据库,并内置了身份验证。但它有一条 AI 工具并不总会遵守的规则。一旦漏掉,任何人只要打开浏览器的开发者工具,就能读取应用的数据。
本指南介绍如何在大约十分钟内检查你自己的应用,无需安装任何东西。
为什么应用里的密钥是公开的
你的应用在浏览器中与 Supabase 通信,因此浏览器需要一个密钥。这个密钥叫作 anon key(较新的项目中叫 publishable key),会随应用的 JavaScript 一起发布,任何人都能找到它。这是设计使然。
保护数据的不是密钥,而是 Row Level Security(RLS,行级安全):数据库中的规则,决定每个访问者可以读取或修改哪些行。开启 RLS 并配好规则,公开的密钥就无害;关闭 RLS,公开的密钥就能读取整张表。
| 情况 | 持有你公开密钥的陌生人能做什么 |
|---|---|
| 数据表未开启 RLS | 读取(通常还能修改)所有行 |
| 开启 RLS,但没有规则 | 什么也做不了:所有请求都会被拒绝 |
开启 RLS,规则为 using (true) |
对于规则涵盖的操作和角色,等同于未开启 RLS |
开启 RLS,规则基于 auth.uid() |
只能访问属于当前登录用户的行 |
第 1 步:列出未开启 RLS 的数据表
在 Supabase 控制台中打开你的项目,进入 SQL Editor,运行:
select c.relname as table_name,
c.relrowsecurity as rls_enabled
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public'
and c.relkind = 'r'
order by c.relrowsecurity, c.relname;每一行 rls_enabled = false 都是公开密钥可以访问的数据表。在 Table Editor 中创建的表默认开启 RLS;通过 SQL 创建的表则不会,而大多数 AI 工具正是用 SQL 建表的。
控制台中的 Security Advisor 也会把同样的问题标记为 RLS Disabled in Public。如果它显示了任何错误,先从那里着手。
第 2 步:查找放行一切的规则
开启了 RLS 但规则过于宽松,同样等于敞开大门。列出你的规则:
select tablename, policyname, cmd, roles, qual, with_check
from pg_policies
where schemaname = 'public'
order by tablename, cmd;仔细检查 qual 或 with_check 直接为 true 的规则,尤其是针对 anon 或 public 角色的规则。如果 profiles 或 orders 表上有这样的规则,就意味着任何人都能读取所有用户资料或所有订单。
第 3 步:从外部确认
现在像攻击者一样测试:只用公开密钥。在 Project Settings → API 中找到项目 URL 和密钥,然后运行:
curl "https://YOUR-PROJECT.supabase.co/rest/v1/profiles?select=*&limit=5" \
-H "apikey: YOUR_PUBLIC_KEY"如何解读结果:
- 返回了不属于你的数据:这张表已经暴露,请今天就修复。
- 返回空列表
[]:要么表是空的,要么 RLS 把所有数据都过滤掉了,这正是你想要的结果。 - 返回权限错误:这张表完全无法通过 API 访问,同样没问题。
对每一张存放个人信息、支付数据或其他私密内容的表重复这个测试。
第 4 步:确认应用中没有私密密钥
Supabase 还会提供 service role key(或以 sb_secret_ 开头的 secret key)。它会完全绕过 RLS,只能存放在服务器上。打开你已上线的应用,按 F12,进入 Sources,在 JavaScript 中搜索 service_role 和 sb_secret_。只要出现其中任何一个,就立即在控制台中轮换该密钥,并把需要它的代码移到服务器端函数中。
应该先修复什么
- 轮换所有已经暴露到浏览器中的私密密钥。
- 为 public schema 中的每张表开启 RLS:
alter table public.profiles enable row level security; - 把私密数据表上的
using (true)规则替换为基于当前登录用户的规则。 - 再次执行第 3 步,确认陌生人什么也拿不到。
开启 RLS 后,所有依赖那张开放数据表的页面都会失效。这是预料之中的:每个页面现在都需要一条恰好放行其所需数据的规则。如果你的应用是由 AI 生成的,而你不确定它需要哪些规则,这正是我们的 Security Check 首先要做的工作。
SupabaseLovableRow Level SecurityAI 开发的应用
继续阅读
全部文章
应用安全
在浏览器里发现了 Supabase 的密钥?第一个小时该做什么
前端中的 service role 密钥或 secret 密钥,会让任何人完全掌控你的数据库。正确的顺序是:作废、替换、查看日志,再修复根源。
阅读约 5 分钟

网站
网站联系表单的邮件为什么会进垃圾箱?SPF、DKIM 和 DMARC 如何解决
网站表单发来的邮件进了垃圾箱,甚至根本收不到?问题通常不在内容,而在发送方式。本文介绍要检查什么,以及需要配置的三条 DNS 记录。
阅读约 5 分钟