AI 开发应用审计清单:向真实用户收费前,我会检查什么

Rushiraj Jadeja 2026-09-01T23:51:28.090634

先坦白一件事:我还没审计过别人的应用。我做过的,是把自己做的六个产品从头到尾审了一遍——两个赚钱的逐行检查,剩下四个端到端过了一遍——用的是攻击者和付费用户的视角。这六个产品全部重度依赖 AI 辅助完成,上线很快。当时我默认一切正常,理由仅仅是界面上看起来一切正常。

以下问题,全出在我自己亲手写、亲手测试、并且向用户收过费的软件里:

六个问题,全部出在我以为正在正常工作的软件

这就是AI构建应用特有的危险。Lovable、Bolt、v0、Cursor、Replit这些工具非常擅长把东西做得“看起来像是完成了”——演示Demo里主流程跑得通。但它们不保证那些你看不见的路径真的存在,比如webhook回调、错误处理、数据库规则,以及“按钮变绿”和“事情真的发生”之间的那段空隙。

所以,在向真实用户收费之前,请对照这份清单自查一遍。这份清单是我从自己踩过的坑里攒出来的,每一项都有10分钟内能完成的检查方法,不需要任何特殊工具。

1. 支付与权益的完整性

最贵的故障都出在这一环——因为这里是真金白银的流向,而背后依赖的逻辑可能从没被人验证过。

检查项:webhook 真的存在吗?

所谓“客户端成功处理”,就是浏览器从结账页跳转回来,页面显示“已支付”,你的应用就授予访问权限。但浏览器可能崩溃,标签页可能被关掉,重定向可能失败。一旦这些发生,你就是“钱收了,东西没给”——而且服务端没有任何记录可以帮你补救。

10分钟检查法:打开你的 Stripe(或 Razorpay、Paddle)控制台,看看有没有配置好的 webhook 端点(支付平台向你的服务器发通知的回调接口)。然后在代码里找对应的处理函数——搜索 webhook 关键字,以及签名校验的调用(Stripe 里是 constructEvent)。如果控制台里压根没有端点,或者授权逻辑出现在 webhook 处理函数之外的任何地方,那你很不幸,中了我踩过的那个坑。这时候你可以自己在测试模式下买一次自己的产品,付完款立刻关掉标签页,看看是否会收到你付钱买的东西。

检查项:付费墙是真的,还是只是装饰?

我之前那些“已锁定”的文档,其实只是用 CSS 滤镜做了模糊处理。内容完整地躺在页面里——这把“锁”只是对浏览器的一句“礼貌请求”,让它别把已经拿到的东西显示出来。

10分钟检查法:打开一个锁定页面,右键选择“查看页面源代码”(或者打开开发者工具,把模糊/遮罩元素删掉)。如果高级内容能直接读出来,那你的付费墙就是纯装饰。正确的解法在服务端:未付费的客户端,根本不该收到被保护的内容。对“隐藏”的高级功能也做一遍同样的测试——检查它们背后的 API 接口是否真的校验了付费权益,还是仅仅相信了“按钮被藏起来了”这件事。

检查:客户能找回自己的购买记录吗?

我的恢复购买流程之所以失败,原因比流程本身更深一层:购买时根本没有记录邮箱。没有标识,拿什么去恢复?AI 工具只会按你的要求把流程搭出来,不会追问这个流程依赖的数据到底存不存在。

十分钟检查:用测试模式买一次,清掉 cookies(或开一个无痕窗口),然后只凭真实客户手里会有的东西——收据邮件——试着找回购买记录。如果你都找不回来,客户更不可能。每一次换设备、每一次清缓存,都会变成一笔退款申请。

2. 静默失败检测

我的 AI 生成功能并没有崩溃。这才是问题所在。代码捕获了「缺少 API 密钥」的错误,回退到静态模板,然后以 200 状态码照常返回。一切显示正常,功能却死了整整六个月。

AI 生成的代码特别喜欢这种写法——try/catch 把错误吞掉,再返回一个看起来合理的结果。表面上是健壮性,实际上是个能把故障无限期藏起来的机制。

检查:关键路径上的故障,会大声报警吗?

十分钟检查:挑出你最重要的功能——就是用户付费买的那一个。在本地环境里,删掉它依赖的 API 密钥,然后实际用一次。如果看到明确的报错,很好。如果看到一个貌似正常的返回结果,那你手里就埋着一颗静默失败的雷,只等某天密钥过期、配额用尽、或者某个环境变量在迁移中没保住。我的环境变量就是在迁移中丢的,而且没有任何警报告诉我。

十分钟检查:在代码库里 grep 一下 catch,把每个块都读一遍。任何返回兜底内容、空数组或 null 的 catch,只要没记日志、没发警报,就是一处「应用悄悄死了都不通知你」的隐患。开服第一天不一定非要上全套监控体系——一个会真正去看的 console.error,或者一封发给你自己的邮件,都比一个被吞掉的异常强。

检查:输出真的会变化吗?

如果你的「AI 驱动」功能返回结果稳定得可疑,就测一下:同一个请求跑两遍,再跑两个差异很大的请求。静态模板的兜底结果,结构完全一致,只是换了换里面的名词。我本该早点发现。但我没去看。

3. 认证与数据安全(含 Supabase 行级安全)

我研究过的 AI 构建应用,大多数都用 Supabase,而那些翻车案例也大多根出同源:行级安全(Row Level Security,RLS)要么压根没开启,要么策略是 AI 为了「让报错消失」而随手编出来的。

检查项:RLS 真的开了吗?策略是真能用的吗?

前端 JavaScript 里的匿名密钥(anon key)本来就是公开的——这是设计使然。在这把公开钥匙和你的整个数据库之间,唯一能挡刀的只有 RLS 策略。如果一张用户数据表上写了一条 USING (true) 的策略,那就意味着任何人只要拿到你的网址和匿名密钥(两样都能在网页源码里看到),就能读走表里的每一行。

十分钟检查法:打开 Supabase 控制台,逐张表确认 RLS 已启用。然后读策略——别只看名字,要看条件。凡是涉及用户数据的表,策略里没有引用 auth.uid()(或等效的所有权校验)的,都值得怀疑。再做一次实战测试:从你已部署站点的源码里复制出匿名密钥,在终端里试着查另一个用户的数据行。你自己能查到,就代表任何人都能查到。

检查项:客户端打包文件里暴露了什么?

十分钟检查法:在部署后的应用上查看源代码,搜索 keysecretsk_ 之类关键词。凡是以 NEXT_PUBLIC_ 开头(或你所用框架的对应写法)的内容,都会原样发给每一个访问者。匿名密钥和可发布密钥(publishable key)放这里没问题;但 service-role 密钥、OpenAI 或 Resend 的 API 密钥、以及一切名字里带 secret 的东西都不该出现在这里——而 AI 工具为了不报 CORS 错误,会高高兴兴地把它们塞进去。

检查项:用户能不能通过 API 摸到彼此的数据?

十分钟检查法:创建两个测试账号。用账号 A 登录,打开开发者工具,找一条拉取 A 数据的请求,把里面的 ID 换成 B 的再重放一次。如果返回的是 B 的数据,说明你的鉴权只存在于界面层,而不是后端。

4. 潜在客户与联系表单流程

联系表单是你网站上最不起眼的功能,也是出了问题你永远听不到反馈的功能——因为被它坑的,恰恰是那些正在想方设法联系你的人。

我的那个甚至算不上"坏掉"——它是在做戏:一个 setTimeout、一段成功动画,却没有任何真正发出内容的网络请求。构建它的 AI 接到的是"做一个联系表单"的需求,也确实制作了一个和真表单几乎无法区分的东西,直到消息真正送达的环节才露馅。

检查项:给自己发一条消息。

十分钟检查:在正式线上站点(不是 localhost)上填写自己的联系表单,确认消息真的到达了你平时会查看的地方。然后再检查失败路径:如果投递失败,用户会看到什么?如果答案是"同样的成功提示",那你就是在欺骗潜在客户。

检查项:备份真的存在吗?

如果表单声称会把提交内容存进数据库作为后备方案,那就打开数据库,找出那张表。我的就没有——每次提交,插入操作都悄悄失败(见第二节),而邮件路径又是假的,所以整体投递率为零。

十分钟检查:提交表单,然后查看数据库的实际行和真实收件箱。凡是你没有亲眼看到抵达的消息,一律不要相信。

5. 部署与仓库卫生

这一项看起来像走流程,直到它害你重做一轮设计才会引起重视。我差点就吃了这个亏:我跨多台机器开发,而手头正在用的克隆仓库,已经悄悄落后于生产环境实际部署的分支达 9 个月。本地仓库显示一套,生产环境是另一套,在那个过时的克隆上开发"新"功能,险些让整个重新设计在几小时内就被回滚。

检查项:仓库和生产环境一致吗?

十分钟检查:从生产环境部署的那个分支拉一个干净的克隆,做一次全新构建,再和线上站点对比。对比几个页面就够了——如果文案、样式或功能和你本地工作副本构建出来的结果不一致,说明已经发生漂移,而每一次部署都像拿着一把上了膛的枪。解决办法不是某个工具,而是一条规则:生产环境只能通过仓库发布变更,每台机器在构建之前必须先拉取。不允许直接改服务器,不允许"我晚点再同步",没有任何例外。

检查项:能从头开始部署吗?

十分钟检查:把代码仓库克隆到一个新目录,然后只按照 README 里的说明尝试运行。缺少的环境变量、没写进文档的安装步骤、只存在于你电脑上的依赖,全都会立刻现出原形。而每一项都会在你顶着压力部署上线的那天捣乱——偏偏部署出问题就是在这种时候。

检查项:你的环境变量都覆盖了吗?

把你代码里读取的所有环境变量列出来(用 grep 搜 process.env),再和托管平台后台实际配置的变量一一对照。我之前一个AI功能整整六个月是坏的,原因正是如此:有个密钥在一个环境里有、另一个环境里没有,而且启动时没有检查去发现它。只要一个十行的启动断言脚本,就能让我少卖半年坏功能。

这一切的重点

这份清单上的每一项,在界面上都看不见。这个现象值得记住:AI建的应用里,真正要紧的故障几乎从不在正常路径上。演示能跑,截图是真的。漏洞藏在 webhook、catch 块、数据库策略,以及那个“绿色对勾”和真实事件之间的缝隙里。

查看原文