Lovable 2026安全漏洞:暴露密钥、缺失RLS及审计发现
我在过去三个月里审计了客户在 Lovable 上构建 MVP 后带来给我们的应用。这个规律非常一致,几乎令人厌倦:客户端包中暴露的 Supabase 服务密钥、零 RLS 策略、硬编码的 OpenAI 和 Stripe 密钥就在 JavaScript 中,任何人用 DevTools 就能获取。每一次都是这样。
这不是对 Lovable 的批评。这个平台对于原型设计来说真正令人印象深刻。但"可工作的演示"和"生产就绪的应用"之间存在着一个巨大的鸿沟,而 Lovable 没有告诉你这个鸿沟中的大部分内容。一位社区研究人员审计了 50 个 AI 构建的应用,发现其中几乎所有应用都存在相同的五个安全错误。另一位开发人员扫描了 200 多个临时编码的网站,发现平均安全分数为 100 分中的 52 分——最坏的违规者集中在特定的 Lovable + Supabase 应用中。
让我们来逐一审视我们不断发现的每个漏洞、为什么 Lovable 自身的工具会遗漏它们,以及如何修复每一个。
目录
- 导致问题的架构
- 漏洞 1:客户端代码中暴露的 Supabase 密钥
- 漏洞 2:缺失或损坏的 RLS 策略
- 漏洞 3:硬编码的第三方 API 密钥
- 漏洞 4:缺失安全标头
- 漏洞 5:无输入验证或清理
- Lovable 的内置安全扫描实际检查的内容
- 生产审计捕获的平台未检查的内容
- Moltbook 事件:真实案例研究
- 在投入生产前修复 Lovable 应用的方法
- 自动扫描工具
- 常见问题

导致问题的架构
要理解为什么 Lovable 应用受到的影响不成比例,你需要了解其架构。Lovable 专门使用 Supabase 作为其后端。没有 Firebase 选项,没有自定义后端,没有逃生舱。当你在 Lovable 中构建某些内容时,它生成一个 React 前端,该前端使用客户端库直接与 Supabase 的 REST API 通话。
Supabase 的设计使得 anon 密钥可以安全地公开暴露——它本质上是一个项目标识符。安全模型完全依赖于 PostgreSQL 级别的行级安全 (RLS) 策略。这样想它:
| 组件 | 可以是公开的吗? | 什么保护你 |
|---|---|---|
| Supabase URL | 是 | 不需要任何东西——它只是一个 URL |
anon 密钥 |
是 | 每个表上的 RLS 策略 |
service_role 密钥 |
绝对不行 | 必须仅保留在服务器端 |
| 数据库连接字符串 | 不 | 永远不要暴露给客户端 |
问题在于 Lovable 的 AI 生成的代码经常以相同的方式对待所有这些。它将 anon 密钥放在前端(很好),但随后创建启用 RLS 的表(灾难性)。有时它也会将 service_role 密钥放在客户端代码中(游戏结束)。正如 Reddit 上的一位开发人员所说的:"AI 会做你要求的事情。它只是从不考虑你没有要求的事情。"
漏洞 1:客户端代码中暴露的 Supabase 密钥
每个 Lovable 应用都用某种方式初始化 Supabase 客户端:
// src/integrations/supabase/client.ts
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = 'https://xyzcompany.supabase.co'
const supabaseAnonKey = 'eyJhbGciOiJIUzI1NiIs...'
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
anon 密钥在这里是很好的——那是按设计的。问题有两种形式:
`service_role` 密钥泄露
我们看到过 Lovable 生成的代码,其中 service_role 密钥最终出现在客户端代码中,通常是因为有人向 AI 提示了类似"即使 RLS 阻止它也要让这个工作"的内容。AI 的解决方案?使用管理员密钥。service_role 密钥完全绕过所有 RLS 策略。如果它在你的前端包中,任何人都可以提取它并拥有对你整个数据库的完整读/写访问权限。
提交到 Git 的 `.env` 文件
部署到 GitHub 的 Lovable 项目经常将 .env 文件提交到存储库中。即使该存储库现在是私有的——即使只是一分钟——那些密钥也被泄露了。机器人不断地扫描 GitHub 以寻找完全这种模式。
如何检查:
# 在代码库中搜索 service_role 密钥
grep -r "service_role" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.env" .
# 检查 git 历史以查找意外提交的密钥
git log --all -p -- '*.env'
如何修复: 立即从所有客户端代码中删除 service_role 密钥。在你的 Supabase 仪表板中轮换该密钥(设置 → API)。仅在服务器端代码中使用该密钥——Supabase Edge 函数、Next.js API 路由或单独的后端。
漏洞 2:缺失或损坏的 RLS 策略
这是大问题。CVE-2025-48757 暴露了 170 多个应用中 303 个易受攻击的端点。根据 Escape.tech 的数据,83% 的暴露 Supabase 数据库涉及 RLS 错误配置。
以下是 Lovable 创建表时默认发生的情况:
-- Lovable 经常生成什么
CREATE TABLE user_profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES auth.users(id),
full_name TEXT,
email TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
-- 注意缺少什么?RLS 没有被启用。
-- 任何拥有 anon 密钥的人都可以完全读取和写入此表。
没有 RLS,你的 Supabase 数据库本质上是一个公共 API。任何知道你的项目 URL 和 anon 密钥的人——两者都在你的前端代码中——可以做到这一点:
// 攻击者的浏览器控制台
const { data } = await supabase.from('user_profiles').select('*')
// 返回每个用户的数据
await supabase.from('user_profiles').delete().neq('id', '')
// 删除一切
RLS 失败的三种形式
| 失败模式 | 发生什么 | 严重性 |
|---|---|---|
| RLS 完全未启用 | 完整的公共读/写访问 | 严重 |
| RLS 启用但未定义策略 | 没有人可以访问任何东西(应用中断) | 高(迫使开发者禁用 RLS) |
过于宽松的策略(例如 USING (true)) |
看起来安全,实际上不安全 | 高 |
第三个特别阴险。当提示要"修复权限"时,我们看到 Lovable 生成这样的策略:
CREATE POLICY "Allow all access" ON user_profiles
FOR ALL
USING (true)
WITH CHECK (true);
这是 RLS 剧场。它被启用了,它有一个策略,它什么都不做。
一个适当的策略看起来像这样:
-- 启用 RLS
ALTER TABLE user_profiles ENABLE ROW LEVEL SECURITY;
-- 用户只能读取自己的资料
CREATE POLICY "Users read own profile" ON user_profiles
FOR SELECT
USING (auth.uid() = user_id);
-- 用户只能更新自己的资料
CREATE POLICY "Users update own profile" ON user_profiles
FOR UPDATE
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
-- 只有经过身份验证的用户可以插入,并且只能为自己插入
CREATE POLICY "Users insert own profile" ON user_profiles
FOR INSERT
WITH CHECK (auth.uid() = user_id);

漏洞 3:硬编码的第三方 API 密钥
这个让我每次都感到难受。我们经常发现 OpenAI API 密钥 (sk-...)、Stripe 密钥 (sk_live_...)、SendGrid 密钥和其他凭证直接硬编码在 React 组件中。
// 实际上在 Lovable 生成的文件中发现
const openai = new OpenAI({
apiKey: 'sk-proj-abc123...', // 这在你的浏览器包中
})
任何打开 DevTools、进入 Sources 选项卡并搜索 sk- 或 sk_live 的人都会获得你的密钥。攻击者自动执行此操作。有机器人专门爬取 JavaScript 包以寻找这些模式。
财务影响是真实的。我们有一个客户来找我们,他们暴露的 OpenAI 密钥在一个周末内导致了 4,200 美元的费用。Stripe 密钥更糟——它们授予处理退款、查看客户数据和修改订阅的完整访问权限。
修复方案: 将所有第三方 API 调用移动到服务器端函数。Supabase Edge 函数对此很好:
// supabase/functions/openai-proxy/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
serve(async (req) => {
const { prompt } = await req.json()
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${Deno.env.get('OPENAI_API_KEY')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-4o',
messages: [{ role: 'user', content: prompt }],
}),
})
return new Response(JSON.stringify(await response.json()))
})
漏洞 4:缺失安全标头
扫描的 200 多个网站发现大多数 Lovable 部署的应用都没有安全标头。没有内容安全策略。没有严格传输安全。没有 X-Frame-Options。没有 X-Content-Type-Options。
这与暴露的数据库相比可能看起来很小,但缺失的标头启用:
- 点击劫持 ——你的应用可以嵌入在恶意网站上的 iframe 中
- XSS 放大 ——没有 CSP,注入的脚本没有限制
- MIME 类型嗅探攻击 ——浏览器可能会将文件解释为可执行代码
- 降级攻击 ——没有 HSTS,流量可以被拦截
| 标头 | 目的 | Lovable 默认值 |
|---|---|---|
| Content-Security-Policy | 防止 XSS,控制资源加载 | 缺失 |
| Strict-Transport-Security | 强制 HTTPS | 缺失 |
| X-Frame-Options | 防止点击劫持 | 缺失 |
| X-Content-Type-Options | 防止 MIME 嗅探 | 缺失 |
| Referrer-Policy | 控制引荐信息 | 缺失 |
| Permissions-Policy | 控制浏览器功能 | 缺失 |
漏洞 5:无输入验证或清理
Lovable 生成的表单通常直接将用户输入发送到 Supabase,没有任何验证。没有长度检查、没有类型验证、没有 HTML 或类似 SQL 内容的清理。
虽然 Supabase 的 PostgREST 层防止了传统的 SQL 注入,但缺乏输入验证仍然启用:
- 通过文本字段中未清理的 HTML 进行的存储型 XSS
- 通过极其大的有效负载进行的拒绝服务
- 业务逻辑滥用(例如,负数量、零价格)
- 来自意外类型的数据损坏
Lovable 的内置安全扫描实际检查的内容
Lovable 有一个内置的"安全扫描"功能,可从仪表板访问。该功能存在值得表扬。但以下是它实际涵盖的内容与它不涵盖的内容:
| 检查 | 内置扫描 | 生产审计 |
|---|---|---|
| 基本语法错误 | ✅ | ✅ |
| 已知的依赖 CVE | 部分 | ✅ |
| 源中的硬编码密钥 | ❌ | ✅ |
| 所有表上启用的 RLS | ❌ | ✅ |
| RLS 策略正确性 | ❌ | ✅ |
| Service_role 密钥暴露 | ❌ | ✅ |
| 安全标头 | ❌ | ✅ |
| 输入验证覆盖 | ❌ | ✅ |
| 身份验证配置审查 | ❌ | ✅ |
| 存储桶策略 | ❌ | ✅ |
| 速率限制 | ❌ | ✅ |
| Cookie 安全标志 | ❌ | ✅ |
内置扫描最多是表面级别。它不会捕获实际被利用的漏洞。
生产审计捕获的平台未检查的内容
当我们为建立在 Lovable 上的客户进行生产安全审计时,以下是我们通常发现和修复的内容。这是真实的列表,来自实际的项目:
数据库层
- 禁用 RLS 的表(平均:60-70% 的表)
- 使用
true作为条件的 RLS 策略 - 缺少 DELETE 操作的策略(开发者忘记了删除)
- 联接/连接表上没有策略
- 设置为公开且没有上传限制的存储桶
- 在 RLS 策略条件中使用的列上缺少索引(性能 + 安全)
身份验证层
- 弱 JWT 密钥(Supabase 默认值很好,但有时人们会更改它们)
- 缺少电子邮件确认要求
- 身份验证端点上没有速率限制
- 没有适当令牌过期时间的密码重置流
- OAuth 重定向 URL 错误配置
客户端代码层
- 前端包中的
service_role密钥 - 硬编码在组件中的第三方 API 密钥
- 提交到 git 历史记录的
.env文件 - 在控制台中暴露用户数据的调试日志
- 泄露数据库架构信息的错误消息
基础设施层
- 完全没有安全标头
- 没有
Secure、HttpOnly或SameSite标志的 Cookies - 暴露的服务器版本信息
- 没有 CORS 配置(接受来自任何来源的请求)
- 依赖项具有已知的 CVE,几个月来未更新
我们审计的典型 Lovable 应用需要 15-25 个修复才能投入生产。大多数的修复时间不到一小时,但你需要先知道它们存在。
Moltbook 事件:真实案例研究
2026 年 1 月,Wiz 的安全研究人员发现 Moltbook ——一个 AI 社交网络——其整个 Supabase 数据库通过配置错误的客户端暴露。anon 密钥在前端 JavaScript 中(正常),但关键表上没有配置 RLS(灾难性)。
结果?150 万个 API 密钥是可访问的。不仅仅是用户数据——还有属于已连接他们的 OpenAI、Anthropic 和其他帐户的用户的实际 API 密钥。对每个表的完整读写访问权限。一个研究人员只需在浏览器控制台中使用 Supabase 客户端就可以浏览整个数据库。
披露时间表很紧凑——Moltbook 的维护人员在被联系后的数小时内修复了关键表。但损害窗口是未知的。数据库在任何人检查之前暴露了多长时间?没有人知道。
这是大规模的 Lovable + Supabase 模式。该平台生成有效的代码。它只是不生成安全的代码。
在投入生产前修复 Lovable 应用的方法
以下是我们使用的检查清单。如果你对 SQL 和 Supabase 仪表板感到满意,你可以自己完成大部分工作:
第 1 步:审计每个表的 RLS
-- 在 Supabase SQL 编辑器中运行此命令以查找没有 RLS 的表
SELECT schemaname, tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public';
任何 rowsecurity 为 false 的表都需要立即处理。
第 2 步:搜索你的代码库以查找密钥
# 搜索常见的密钥模式
grep -rn 'sk-' --include='*.ts' --include='*.tsx' --include='*.js' .
grep -rn 'sk_live' --include='*.ts' --include='*.tsx' --include='*.js' .
grep -rn 'service_role' --include='*.ts' --include='*.tsx' --include='*.js' .
grep -rn 'SUPABASE_SERVICE' --include='*.ts' --include='*.tsx' --include='*.env' .
第 3 步:编写适当的 RLS 策略
对于每个表,为 SELECT、INSERT、UPDATE 和 DELETE 编写显式策略。始终使用 auth.uid() 检查:
-- 用户拥有的表的模板
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
CREATE POLICY "select_own" ON your_table FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "insert_own" ON your_table FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "update_own" ON your_table FOR UPDATE
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "delete_own" ON your_table FOR DELETE
USING (auth.uid() = user_id);
第 4 步:将 API 调用移动到服务器端
任何需要密钥的第三方 API 调用都需要在 Supabase Edge 函数或单独的后端中运行。这是不可协商的。
第 5 步:添加安全标头
如果你正在部署到 Netlify、Vercel 或 Cloudflare,通过它们的配置添加标头。对于 Netlify,创建一个 _headers 文件。对于 Next.js 应用,在 next.config.js 中添加它们。
第 6 步:考虑框架迁移
对于 MVP 以外的任何内容,我们经常建议将 Lovable 生成的 React 代码迁移到适当的 Next.js 或 Astro 项目。这为你提供了服务器端 API 路由、正确的环境变量处理、用于身份验证检查的中间件以及真正的构建管道。这在前期需要更多工作,但安全态势是天壤之别。
自动扫描工具
为审计 AI 生成的应用而出现的几种工具:
| 工具 | 检查的内容 | 成本 |
|---|---|---|
Ship Safe (npx ship-safe audit .) |
RLS、service_role 暴露、存储桶、依赖 CVE | 免费、开源 |
| Vibe App Scanner (vibeappscanner.com) | 针对 AI 构建应用的完整安全扫描 | 免费入门扫描 |
| Snyk | 依赖漏洞、代码扫描 | 免费层可用 |
| Supabase 仪表板 → 身份验证 → 策略 | 视觉 RLS 策略编辑器 | 包含在 Supabase 中 |
Ship Safe 是我开始的工具。它在本地运行,没有任何内容离开你的机器,它专门为 AI 工具创建的 Supabase 错误配置而构建:
npx ship-safe audit .
它会标记禁用的 RLS、客户端代码中的 service_role 密钥、打开的存储桶、弱身份验证配置、硬编码的密钥和依赖 CVE。
常见问题
Supabase anon 密钥在前端代码中暴露是安全的吗?
是的——但前提是你在每个表上都有适当的 RLS 策略。anon 密钥被设计为公开的。它就像一个项目标识符。安全来自 RLS 策略,这控制该密钥实际可以访问的内容。没有 RLS,anon 密钥会给任何人完整的数据库访问权限。
Lovable 在创建表时默认启用 RLS 吗? 不。截至 2026 年初,Lovable 创建的 Supabase 表默认情况下未启用 RLS。这是该平台最大的单一安全差距。你需要在 Lovable 生成它们后手动为每个表启用 RLS 并编写策略。CVE-2025-48757 是这种默认行为的直接结果。
如何检查我的 Lovable 应用是否暴露了密钥?
在浏览器中打开你部署的应用,打开 DevTools(F12),进入 Sources 选项卡,并跨所有文件搜索 sk-、sk_live、service_role 和你使用的服务的任何 API 密钥前缀。同时在代码库上本地运行 npx ship-safe audit . 进行自动检测。
Lovable 的内置安全扫描能捕获 RLS 问题吗? 内置安全扫描不会检查 RLS 错误配置、缺少的策略或暴露的服务密钥。它涵盖基本的代码级问题,但遗漏代表最高风险的数据库和基础设施漏洞。你需要外部工具进行真正的安全评估。
CVE-2025-48757 发生了什么? CVE-2025-48757 是一个漏洞披露,确定了通过 Lovable 构建的 170 多个应用中的 303 个易受攻击的 API 端点。根本原因是 Lovable 创建的 Supabase 表未启用 RLS,使整个数据库可被任何拥有公开可用 anon 密钥的人访问。它突出了问题的系统性。
对于生产应用,我应该迁移离开 Lovable 吗? 不一定。Lovable 对于快速原型和构建 MVP 非常出色。但生成的代码在投入生产使用前需要大量安全加固。许多团队使用 Lovable 构建初始版本,然后迁移到适当的框架,具有服务器端渲染、正确的密钥管理和安全中间件。这是一个合理的方法。
为生产保护 Lovable 应用需要多长时间? 对于一个有 10-20 个表的典型应用,预期需要 2-5 天的专注工作来审计所有 RLS 策略、将密钥移动到服务器端、添加安全标头、验证输入并测试一切。具有存储桶、实时订阅和多个用户角色的更复杂应用可能需要更长的时间。这不是一个不可克服的任务,但也不是一个一小时的任务。
Bolt 或 Cursor 等其他 AI 应用构建器比 Lovable 更安全吗? 超过 200 个网站的扫描发现,安全漏洞集中在特定的 Lovable + Supabase 应用中。Bolt、Replit 和基于 Cursor/Cline 的应用没有显示相同的 RLS 错误配置模式。这并不意味着它们完全安全——所有 AI 生成的代码都需要审查——但 Lovable 特定的 Supabase 集成创建了一个独特的数据库暴露漏洞类别,其他工具没有。