FixVibe

// docs / security guides / pre-launch SaaS

SaaS 上线前安全检查清单:35+ 项

您只需几天时间即可推出使用 Cursor、Claude Code、Lovable 或 Bolt 构建的 SaaS 产品。该清单是一项 go/no-go 审计,涵盖了 AI 工具经常忽略的安全表面,以及快速发货的创始人在拿走客户资金之前需要解决的安全问题。八个部分,超过 35 个项目,每个部分可在 30-90 分钟内解决。打印它,划掉它,自信地部署。

下面的每一项都是必不可少的。绿色表示已发货并已验证;红色表示未解决并阻止启动。有关每个类别的详细演练(包含代码片段和实际故障模式),请参阅How to secure an app built with AI coding toolsThe vibe coding security checklist

客户数据隔离

在多租户 SaaS 中,第一个安全边界是数据隔离。每个客户的数据都必须无法被其他客户访问,这是在数据库层而不是应用程序层强制执行的。

  1. 使用ALTER TABLE public.table_name ENABLE ROW LEVEL SECURITY; ALTER TABLE public.table_name FORCE ROW LEVEL SECURITY; 在每个Supabase 表上启用行级安全性(RLS)。 FORCE 防止表所有者绕过它。
  2. 对于每个 RLS 策略,验证经过身份验证的用户或组织的谓词范围。示例:CREATE POLICY "users_see_own" ON public.items FOR SELECT USING (auth.uid() = user_id);。使用第二个用户帐户进行测试以确认数据保持隔离。
  3. 如果使用 Firebase / Firestore,规则必须与您的租户模型匹配。不要使用allow read, write: if true;或有时间限制的测试规则。使用 allow read, write: if request.auth.uid == resource.data.owner_uid; 或等效的组织范围匹配。
  4. 使用签名 URL 或短期令牌进行文件访问,切勿使用公共存储桶。 Supabase 存储:在objects 表上设置ENABLE ROW LEVEL SECURITY,并制定将文件访问范围限制为经过身份验证的用户的策略。以不同用户身份测试下载。
  5. 在 API 层上,每个请求都必须包含 auth.uid() 或 org-id 上下文。每个数据库查询都必须按该上下文进行过滤。示例:没有SELECT * FROM items WHERE id = $1;总是SELECT * FROM items WHERE id = $1 AND user_id = auth.uid()

计费和付款

Stripe 集成是客户信任与财务安全的结合。这里的配置错误意味着付款被盗、退款循环或收入损失。

  1. 在生产中使用live Stripe keys。在登台时使用单独的测试模式键进行测试。在没有最终实时模式扫描的情况下,切勿将开关从测试切换到实时。
  2. 验证每个入站事件的 Webhook 签名:const event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);。如果签名失败则抛出。仅将 Webhook 机密存储在环境变量中,而不是存储在代码中。
  3. 使用以 event.id 为键的数据库表在 Webhook 处理程序上实现幂等性。如果同一个 Webhook 到达两次(它会),则第二次运行是无操作。将幂等行写入与状态更改相同的事务中。
  4. customer.subscription.updatedcustomer.subscription.deleted 上,立即撤销访问权限。不要等待 cron。通过在Stripe仪表板中取消订阅并验证用户在 5 秒内被锁定来进行测试。
  5. 仅将Stripe 客户ID 和订阅ID 存储在您的数据库中,切勿存储完整的卡或API 密钥。在每个身份验证边界上从 Stripe 检索实时订阅状态(页面加载、API 调用、cron 检查)。不要缓存订阅状态超过 1 分钟。

身份验证和会话

Auth 是 SaaS 中的二阶攻击目标。用户帐户是数据和支付方式的载体。

  1. 在每条受保护的路由上使用supabase.auth.getUser(),切勿使用getSession()getSession() 读取未经验证的cookie; getUser() 验证JWT 服务器端。在 Next.js 中:在提供受保护的内容之前const { data: { user } } = await supabase.auth.getUser();
  2. 在身份验证 cookie 上设置 SameSite=Lax(Supabase 身份验证默认执行此操作)。在 DevTools → 应用程序 → Cookies 中验证。如果您看到SameSite=None,请将sameSite: 'Lax' 添加到您的会话配置中。
  3. 在您自己的管理员帐户上启用MFA。对于面向用户的MFA,在启动之前对其进行端到端测试:注册、注册TOTP 设备、注销、使用TOTP 令牌重新登录、验证其是否有效。
  4. Magic-link 令牌必须在 15 分钟内过期。密码重置令牌必须在 1 小时内过期。会话令牌 (JWTs) 的寿命可以更长 (24h-7d),但每次使用时都必须进行验证。检查您的身份验证提供商的默认设置。
  5. 测试注销完整性:用户单击注销后,浏览器删除身份验证会话,服务器撤销任何令牌,并且用户无法访问受保护的页面。在Supabase 中:调用await supabase.auth.signOut() 并验证JWT 在下一个请求中不再有效。

PII 和合规性

如果您收集电子邮件、姓名、付款信息或任何PII,您就有法律义务:数据最小化、安全存储、按需删除和DPA 准备。

  1. 编写并发布隐私政策(不是可选的,即使对于独立 SaaS 也是如此)。说明您收集哪些数据、原因、保留时间以及用户权利(访问、更正、删除)。使用 Termly 或类似的模板,但可以对其进行自定义。
  2. 实现一个删除帐户API端点,从数据库中清除PII。测试它:创建帐户,添加数据,删除帐户,验证数据是否消失(使用直接数据库检查)。
  3. 为了确保 GDPR / CCPA 合规性,请在 30 天内回复数据主体请求(访问/更正/删除)。记录您的流程。如果您的应用程序基于 EU- 或为 EU 用户提供服务,则需要包含 Stripe、Supabase 和任何处理器的数据Processing 附录 (DPA)。
  4. 加密静态敏感字段(密码由您的身份验证提供商进行哈希处理;但信用卡标记化、API 密钥、机密应使用 pgcrypto 或外部保管库)。切勿存储纯文本信用卡号(请使用 Stripe 标记化代替)。

运营准备情况

安全是持续的。事件响应、监控和操作手册在第一天之前就开始了。

  1. 设置状态页面(Statuspage.io、Uptime Robot 或简单的 index.html)。客户需要知道是否出现停电。更新每个事件。
  2. 记录并测试随叫随到的轮换。谁会在凌晨 2 点的警报中醒来?谁有部署密钥?谁可以撤销受损的令牌?记录下来并在启动前进行防火演习。
  3. 编写安全事件响应操作手册:如果客户报告违规、丢失密钥、服务中断,该怎么办。将其分发给您的团队。测试一种场景(e.g.,模拟密钥泄漏)以验证该计划是否有效。
  4. 备份和恢复过程必须经过测试,而不是理论。可以从备份中恢复吗?计时吧。 Supabase:启用自动备份(免费保留 7 天,付费保留 30 天)。每季度测试一次到单独项目的恢复。
  5. 为特权操作启用审核日志记录:Stripe 仪表板登录、Supabase 管理API 调用、数据库架构更改、付款对账。工具:CloudTrail (AWS)、Supabase 审核日志、PostgreSQL pgaudit 扩展。

外部攻击面

您的API 边界不断受到攻击者扫描。在恶意流量袭来之前将其锁定。

  1. 对每个公共端点进行速率限制。示例:注册时每个 IP 每分钟 100 个请求,密码重置时每分钟 10 个请求。使用 Vercel KV、Redis 或类似的。失败并返回 429(请求过多)。
  2. 将 CAPTCHA(hCaptcha 或 reCAPTCHA)添加到注册和密码重置端点以击败机器人。在接受请求之前验证服务器端的令牌。
  3. 如果可用,请使用WAF(Web 应用程序防火墙):Cloudflare、Vercel Web 应用程序防火墙或AWS WAF。自动阻止已知的恶意 IP 和模式。
  4. 扫描开放的API端点。每月对您的生产域运行一次被动 FixVibe 扫描。检查暴露的调试路径、GraphQL 内省、API 密钥泄漏或配置暴露的结果。
  5. 每季度轮换一次凭证(API 密钥、OAuth 令牌、数据库密码)。记录轮换过程并在可能的情况下将其自动化。

可观察性和记录

当出现问题时,日志就是您的取证记录。从第一天开始就设置它们。

  1. 将日志:Supabase 日志、Vercel 日志、应用程序日志和身份验证日志集中到单个仪表板(Datadog、LogRocket 或自托管ELK)。可搜索,保留至少 90 天。
  2. 安全事件警报:重复登录失败(可能是帐户被接管)、异常API 使用(可能是抓取)、错误高峰(可能是攻击或合法事件)。设置阈值和 Slack 集成。
  3. 为每个特权操作发出审核日志:用户角色更改、新管理员帐户创建、支付方式添加、API 密钥中的范围更改。将它们与应用程序日志分开存储,并保留不可变的保留。

最终验证

在宣布之前,请运行完整的 FixVibe 扫描并以安全眼光审查结果。

  1. 针对您的生产域运行 FixVibe Pro 主动扫描。配置您的域以进行主动测试(DNS TXT 或 HTTP 文件验证)。授权扫描并审查每项发现——特别是关键和严重性高的发现。明确修复或接受每一项。
  2. 启用计划的重新扫描:Pro 计划 → 3 小时、6 小时、12 小时或每天。 Unlimited 计划 → 6 小时、12 小时、每天、每 2 天或每周。与 active IDOR walkingSQL injectionreflected XSS 检查您已验证的域配对。
  3. 配置网络钩子:将FixVibe连接到Slack或电子邮件,以便关键发现实时触发警报。请参阅/docs/webhooks进行设置。
  4. 进行最终的手动代码审查,重点关注 /docs/security-guides/ai-generated-code-security-scanner 中的陷阱:捆绑包中的秘密、RLS/rules、身份验证边界、CSP、中间件放置。使用vibe coding security checklist作为审核模板。

发布日

您已清除清单。充满信心地部署。启动后,积极监控:第一周每天检查FixVibe结果,在1小时内响应警报,并保持扫描计划运行。有关包含代码片段的分步强化指南,请参阅How to secure an app built with AI coding tools

// scan your app

别再读了,去找你应用里的漏洞。

插入 URL — FixVibe 在不到一分钟的时间内运行本指南中的每项被动检查以及 200 多项其他检查。 Free,无需安装,无卡。

  • Free 层 — 每月 3 次扫描,无卡。
  • 针对任何 URL 进行被动扫描 — 无需域验证。
  • 针对 Cursor、Claude Code、Lovable、Bolt、v0、Replit 进行了调整。
  • Coding-agent prompts for code/config findings, plus operator steps for DNS/provider fixes.
SaaS 上线前安全检查清单:35+ 项 — Docs · FixVibe