有人专门写了套审计工具,给Lovable、Bolt、v0、Cursor这些"氛围编程"平台产出的应用做体检。结果挺尴尬——同一批漏洞反复出现,像复制粘贴的bug。

导读:你的SaaS可能正在免费赠送Pro会员

过去几周,安全工程师用VibeScan这款审计工具扫描了一批公开的AI生成应用。他发现,同样的12个问题反复出现。

如果你正在用"氛围编程"方式开发SaaS,发布前花30分钟对照这份清单自查,能帮你避开最常见的自毁模式。

1. 支付接口关闭JWT验证,还没做签名校验

代码里长这样:

# supabase/config.toml

[functions.payment-webhook]

verify_jwt = false

函数内部也没有stripe.webhooks.constructEvent(...)就直接信任请求体。

这意味着什么?这个端点全网可访问。任何人都能用curl伪造一个"type": "checkout.session.completed"的请求,直接修改你profiles表里的数据。结果就是:全网用户免费获得Pro会员。

修复只需改一行代码加一个环境变量:

const event = stripe.webhooks.constructEvent(body, signatureHeader, Deno.env.get("STRIPE_WEBHOOK_SECRET"));

2. 行级安全策略写成USING (true)

典型代码:

CREATE POLICY "authenticated users can read"

ON public.cases FOR SELECT TO authenticated

USING (true);

如果cases表里的记录是"任意记录"而非"我的记录",那任何登录用户都能读取全部数据。开放注册 + USING (true) + 开启RLS = 用一种很精致的方式把你的整个数据库暴露给任何点击"注册"的访客。

修复:按所有权限定范围。

USING (user_id = auth.uid())

同时确保INSERT时用WITH CHECK子句设置user_id = auth.uid()。

3. API密钥带VITE_前缀,直接打包进浏览器

// src/components/ResumeUpload.tsx

const key = import.meta.env.VITE_GEMINI_API_KEY;

任何带VITE_ / NEXT_PUBLIC_ / REACT_APP_前缀的变量都会被打进客户端包。打开DevTools → Network标签 → 找到带Authorization头的请求 → 把密钥复制到Postman就能直接用。

修复:把API调用移到Supabase Edge Function(或Next.js服务端路由),密钥放在服务端。浏览器调用你的端点,你的端点再调用第三方服务。

4. 昂贵接口没有限流