AI 修复安全问题后,扫描通过还缺什么
作者让 Claude 按审计提示修改 Next.js、Supabase、Stripe 演示应用,涉及 32 个文件,再以 LaunchVet 扫描并人工审查代码。文章明确未构建或运行应用,也未执行支付、双用户 RLS、接口及真实数据库验证,结果只能说明静态检查层面的变化。
AI 深度解读
让 AI 按审计报告修完代码,再扫出零问题,应用就能上线了吗?LaunchVet 的开发团队拿一个故意写坏的 Next.js 应用做了回测:Claude 修改或新增了 32 个文件,扫描最终归零,但复查代码仍发现支付事件可能丢失、SSRF 防护可能被绕过。
这次实验最有价值的地方,是作者公开了验证边界:他们没有构建或运行应用,没有执行真实数据库迁移,也没有跑提示词要求的验证步骤。它展示了自动修复能处理什么,也暴露了「报告变绿」离「功能可靠」还有多远。
零告警为什么先要修扫描器
实验对象 ResumeFlash 使用 Next.js、Supabase 和 Stripe。前一篇审计共有 28 项发现,作者展示了其中 10 项及对应修复提示词。这次由 Claude 按提示词修改副本,再用 LaunchVet 扫描并人工读代码。
需要区分两组数字:审计不全是静态扫描。扫描器负责基于模式匹配的部分,共有 16 条规则;原始应用合并重复命中后,得到 21 项发现,包括 5 项 critical、9 项 high、6 项 medium 和 1 项 low。
修复后,v0.1.2 仍报告 3 项:critical、high、medium 各 1 项。问题出在 LV006 涉及的行级安全(Row Level Security,RLS)检查。
Claude 按提示词保留旧迁移,在 20261102000000_fix_rls.sql 中启用 RLS、替换允许所有人访问的策略。这符合数据库迁移的常见做法:已经执行过的迁移保持原样,通过新迁移改变状态。
但扫描器逐个文件检查,没有理解执行顺序,于是继续报告 20261101000000_init.sql 里的旧问题。v0.1.3 增加了追踪后续迁移的逻辑,能够识别后来启用的 RLS 和替换的策略,扫描结果才归零。
这里既有修复成果,也有扫描器纠错。数据库实际是否处于预期状态,仍需执行迁移验证。
零告警只表示工具没有找到它认识的问题。
AI 修掉旧问题,也会留下新的故障路径
作者认为,修复提示词处理了不少机械性问题:把密钥移出浏览器、补充资源归属检查、验证 webhook 签名、使用参数化 SQL,以及补齐缺失页面。不过,第二轮代码检查发现了另一批缺口。
Stripe webhook 用 user_id 执行 upsert,对应表却没有该列的唯一约束。数据库缺少判定冲突的依据,这次更新就无法按预期工作。作者通过读代码发现后,在迁移中补了唯一约束,并设置 onConflict。
依赖修复也出现过实际失败。第一次重新生成锁文件时,@supabase/ssr 要求的 @supabase/supabase-js 版本高于演示项目锁定的版本,安装因 peer dependency 错误停止。作者升级版本、重新生成后,锁文件告警才消失。
还有几处问题,作者明确保留了下来。
支付 webhook 在处理业务前,先记录事件 ID。如果后续处理失败,Stripe 重试时会被当成重复事件,用户升级可能就此丢失。更稳妥的方案是在业务成功后记录,或者把业务修改和事件记录放进同一个事务。去重解决了重复执行,却可能破坏失败重试。
URL 导入功能先通过 DNS 检查目标地址,再调用 fetch。后者会再次解析域名,如果第二次返回内部地址,前面的检查就可能失效。这属于服务端请求伪造(SSRF)防护中的连接目标问题:真正建立连接时,必须使用已经检查过的地址。
限流器则从 x-forwarded-for 读取客户端地址。只有托管平台会覆盖这个请求头时,它才值得信任,否则调用者可能伪造地址。
这些缺口涉及数据库约束、事件执行顺序和部署环境,单靠正则匹配很难判断。
哪些检查必须回到真实环境
作者没有构建或运行应用,没有在真实 Supabase 项目执行 SQL,也没有执行 Stripe CLI 测试、双用户 RLS 测试和 curl 检查。因此,前面的结论来自扫描、安装过程和代码复查,不能当成功能验收结果。
剩余工作也不全在仓库里。Supabase 需要创建私有上传 bucket,并测试其他用户无法读取;Stripe 需要创建价格、设置 STRIPE_PRICE_PRO 和 webhook secret,开启客户门户及试用结束邮件;AI 提供商需要配置月度支出上限,限流器依赖的 Upstash Redis 数据库也要实际创建。
支持邮箱仍需替换,隐私政策、条款和退款页面只是演示模板,作者要求交由律师审阅。
若要复现,原文给出的 Claude Code 安装命令如下:
/plugin marketplace add Lt23live/launchvet
/plugin install launchvet@launchvet
第二行安装完成后,运行 /launchvet:launchvet,也可以直接要求「Run LaunchVet on this app.」。扫描器要求 Node.js 18 或更新版本。
工具不会修改应用代码,会生成 launchvet-report.md。作者声明 LaunchVet 没有服务端、无需注册,扫描脚本不发网络请求;但 Claude Code 仍会读取文件,并照常与 Anthropic 通信。不能把扫描脚本无网络访问理解成整条流程完全离线。
我的判断
我认可这次复查的价值:它同时展示了自动修复的收益和缺口,还承认扫描器曾经误报。对使用 AI 编程的团队,这比单独展示一张绿色报告更有参考意义。
但它没有提供人工修复或其他工具的对照,也没有运行应用来验证结果。「提示词有效」目前主要是这份演示项目上的代码层面观察,不能外推成普遍的修复成功率,更无法判断它节省了多少时间。
LaunchVet 由作者所在的 Grey State Development 开发,免费核心采用 MIT 许可证,包含 26 项检查。Pro 一次性售价为 $19,优惠价 $12 截止到 2026 年 11 月 11 日晚上 11:59(PT),增加支付与 Stripe 上线准备检查、应用商店模块、法律页面模板和 CLAUDE.md 安全规则等内容。作者说明,修复免费版发现的问题不需要购买 Pro。这些商业背景应当和实验结果一起看。
对一般团队,我会把这类工具放在检查遗漏的位置。它能提醒你补签名验证,却未必能判断一次支付失败后能否正确重试。代码审查和集成测试仍然负责后半段。
能拿来做什么
- 给 Next.js 或 Node 应用应用 AI 修复后,先读 diff,再执行报告中的验证步骤,最后重扫;把「告警消失」和「验证通过」分别记录。
- 审查 Stripe webhook 时,沿着失败路径检查事件去重,确认业务处理中断后,重试仍能完成升级,并核对
upsert使用的唯一约束。 - 修改 Supabase 权限时,用新迁移表达变更,再用两个用户测试数据访问和私有文件读取;历史 SQL 被识别为已修复,不能替代实际权限测试。
- 检查 URL 导入和限流代码时,把部署平台也纳入验证:确认连接使用已检查的地址,并查清
x-forwarded-for是否由可信代理覆盖。