网站没报错不代表安全 权限、余额和账单都可能失守 保存这七项上线前检查 别等数据泄露、账单失控

你用 AI 做了一个网站。

按钮能点,Google 能登录,付款也能走通。自己试了几遍,你可能觉得可以上线了。

但这只证明产品在正常操作下能够工作。

网站公开以后,进来的人不一定会按你的流程走。有人会反复领取免费额度,把项目编号——也就是类似订单号的一串标识——换成别人的,跳过付款页面请求付费功能,或者让 AI 写脚本,在很短时间内发送几百次请求。

他们只是在试:改一个数字、跳过一个步骤、多操作几次,你的系统会不会交出不该给他的资料、功能和额度?

Vibe Coding 最危险的情况,不是代码报错,而是代码没有报错,功能也在运行,只不过它执行的是一套有漏洞的权限、额度和付费规则。

安全首先要守住三件事

对一个准备上线的网站来说,安全首先要守住三件事:

  • 不该看见的人,拿不到用户资料;
  • 不该修改的人,改不了权限、余额和付费状态;
  • 不管有人发送多少请求,服务和预算都不会被轻易耗尽。

安全领域把它们叫作机密性、完整性和可用性,英文首字母合起来是 CIA。术语不用背,记住上面三种结果就够了。

先看两个最容易被正常测试漏掉的问题。

页面挡住了,后台没有挡住

假设账号 A 创建了一份私密字幕项目。

账号 B 的页面上没有这个项目,也没有“查看”按钮。看起来似乎很安全。

但如果 B 修改链接里的项目编号,或者绕过页面直接向后台请求,系统会不会把 A 的项目交给他?这里的“后台”,就是在用户看不见的地方真正执行权限判断和数据操作的程序。

这类问题的关键不在页面显示了什么,而在后台是否真的检查了“这份资料属于谁”。

上线前,准备两个普通测试账号 A 和 B:让 A 创建私密内容,再让能够操作测试环境的编程 Agent 或开发者尝试用 B 读取、修改和删除。在没有共享或其他明确授权时,正确结果必须是后台拒绝,而不是页面刚好没有入口。

给 AI 或开发者看的技术补充:这属于授权和用户隔离问题。Supabase 常用 RLS,Firebase 常用 Security Rules。但高权限后台可能绕过这些规则,因此所有后台接口仍要检查用户、目标对象和允许操作。

余额够一次,却跑出了十个任务

用户只剩 8 点,运行一次 AI 任务正好需要 8 点。

如果系统先检查余额,过一会儿才扣点,那么 10 个请求同时进来时,可能都看到“余额足够”。最后,8 点跑出了 10 个任务。

你不需要自己实现并发控制,只需要验收结果:

当余额只够一次时,同时提交 10 次,最后只能成功一次、创建一个任务、扣费一次。

用户付款以后,支付平台通常会向网站后台发送一条“付款成功”的消息,这叫支付通知。同一条付款成功通知即使重复送达,也只能入账一次;伪造通知、错误金额和错误订单必须被拒绝。

给 AI 或开发者看的技术补充:余额预占与任务创建需要不可拆分;重复请求需要幂等键和唯一约束;扣费、退款和结算等财务操作必须幂等。支付回调还要验证签名、时间、金额、币种、客户和订单关系。

如果暂时看不懂原理,先保存这七项

上线前,至少让 AI 或开发者逐项交付下面七类结果。

这里说的 AI,必须是能够实际读取项目代码和配置,并且能在测试环境运行项目的编程 Agent。普通聊天窗口可以给建议,但不能证明产品通过了测试。

  1. 在没有共享或其他明确授权时,两个普通账号不能互相读取、修改或删除资料。
  2. 修改网页传来的价格、角色、项目编号和额度,不会改变后台判断。
  3. 余额只够一次时,并发或重复提交不会创建额外任务,也不会重复扣费。
  4. 支付通知重复或乱序到达不会重复入账;伪造通知和错误订单会被拒绝。
  5. 注册、上传和 AI 调用超过事先规定的次数或预算后,会被限制、排队或拒绝。
  6. 能够取得的代码、日志和网页已经检查;没有发现泄露的秘密凭证,已经泄露的旧凭证则已失效并换新。
  7. 无法检查的平台后台和线上设置被明确列出,而不是写成“没有问题”。

每一项都要附上测试环境、对应版本、操作步骤、实际结果和证据位置。

这七项是权限、付费和资源滥用方面的最低基线,不是完整安全审计。但如果连这些结果都拿不到,就不该用一句“测过了”宣布产品安全。

为什么要先写清楚产品规则

AI 能读代码,却不知道你的产品准备怎么收费。

假设代码规定“登录后都能生成长视频字幕”,它运行得完全正常。但你的真实规则可能是“只有付费用户才能使用”。如果不把这句话告诉 AI,它无法知道这里有问题。

先写下这些不能被打破的规则:

  • 用户只能访问自己的资料,除非得到明确授权;
  • 免费用户不能调用付费功能;
  • 余额不足时不能启动付费任务;
  • 同一个任务只能创建和计费一次;
  • 同一笔付款只能入账一次;
  • 普通用户不能把自己变成管理员。

这些规则在安全领域叫“安全不变量”。说白了,就是不管网络重试、用户乱点还是脚本同时发送多少请求,它们都不能失效。

现在就可以把这张清单交给 AI,让它先追问缺失规则,不要直接开始扫描。

再回答五个问题

1. 哪些东西一旦泄露,会让你损失最大?

以 AI 字幕工具为例,可能包括未公开视频、字幕、账号资料、付费记录、点数余额、管理员权限,以及能够调用第三方 AI 的秘密凭证。

秘密凭证相当于程序访问数据库或第三方服务时使用的后台密码。凡是能读取私密资料、修改后台设置或调用付费服务的凭证,都不能放进公开网页。

先把这些东西列出来,并按损失大小排序。安全不是每个地方平均用力,而是先保护最贵、最敏感、最难挽回的东西。

如果秘密凭证已经出现在网页、公开代码或日志里,不能只删掉那行内容。必须先让旧凭证失效,再生成新的,并检查它是否已经被别人使用。平台里通常把这个过程叫作撤销或轮换凭证。

2. 产品里有哪些人?每个人能做什么?

访客、免费用户、付费用户和管理员能做的事情不同。

Google 登录只能帮助系统确认当前是谁,不能自动保证他有资格读取某份资料或使用某项功能。确认“你是谁”叫身份验证;判断“你能做什么”叫授权。

小白只需要记住一个验收动作:用两个普通账号互相测试,而不是看到登录按钮就宣布权限安全。

3. 资料会经过哪些地方?

用户点击“生成字幕”以后,资料可能经过:

你的电脑 → 网站后台 → 保存文件的地方 → 第三方 AI 服务 → 日志和备份

用户可以修改自己电脑和网页发出的内容,所以网页传来的价格、角色、项目编号和余额都不能直接相信。跟钱、权限和资料归属有关的判断,必须由后台重新计算。

继续问:文件是否公开?下载链接多久失效?AI 服务商收到什么?日志有没有留下用户原文?用户删除以后,各处副本会保留多久?

给 AI 或开发者看的技术补充:完整系统可能还包括 CDN、任务队列、数据库、错误监控和缓存。请把无法读取的平台配置列为覆盖缺口,也就是当前检查没有覆盖到的部分。

4. 哪些入口可以被反复触发?

注册、登录、找回密码、上传、领取免费额度、生成 AI 内容和支付通知,都可能被脚本反复调用。

每个入口都要规定次数、并发数量和费用上限。更重要的是给整个产品设置总预算:即使攻击者不断更换账号或网络,账单也不能无限上涨。

上传文件还要限制类型、大小、数量和处理时间,不能只相信文件名。

5. 哪些地方无法从代码里看见?

低代码平台、云服务和生产后台里,可能还藏着数据库权限、文件公开设置、线上密钥和消费上限。

代码扫描没发现问题,不代表这些设置正确。看不到的地方必须写成“未验证”,交给有后台权限的人逐项检查。

与工具无关的完整流程

无论使用哪一种编程 Agent,安全检查都应该按照同一条路线进行:

  1. 写清需要保护的东西、用户角色和不能破坏的规则。
  2. 列出注册、上传、支付和 AI 调用等外部入口。
  3. 扫描代码和能够取得的配置。
  4. 在本地或明确获准的测试环境中,对具体问题进行实际验证。
  5. 做最小范围修复。
  6. 重新执行原来的测试,证明问题已经消失,正常功能没有被修坏。
  7. 记录没有检查到的代码、平台设置和线上状态。

“代码改过了”和“问题已经修好”不是一回事。没有重新执行原来的测试,就不能写“已经修好”。

如果你使用 Codex Security

Codex Security 只是执行上述流程的一种工具,不是安全本身。当前插件的几个入口大致对应:

  • Define Security Policy:整理项目规则,生成或更新 SECURITY.md;
  • Threat Model:整理资产、外部入口和危险路径;
  • Security Scan:检查整个项目或指定目录;
  • Security Diff Scan:检查某次提交、分支、PR 或本地改动;
  • Fix Finding:处理具体问题并提供修复;
  • Deep Security Scan:用更多时间和资源做更深入的全项目检查。

具体入口可能随版本变化,使用前应查看当前插件说明。没有 Codex Security,也可以把同样的规则和验收要求交给其他能够读取代码、配置并运行测试的编程 Agent。

外包和低代码项目,只认可复查的证据

如果开发者只回复“测过了,没问题”,等于什么也没交。

可以直接把下面这段话发给对方:

请不要只回复“已经测试”。请提供测试环境、对应版本、操作步骤、实际结果、关键证据和无法验证的部分。没有证据的项目一律标记为“未验证”。

低代码项目还要检查平台后台里的数据库权限、文件存储、线上密钥、管理员角色和消费上限。无法导出的内容,由有后台权限的人核对。

给小白按顺序使用的三组 Prompt

下面三组提示词不要一次性全部发送。

先发送第一组,回答问题并确认产品规则;规则确认后,再发送第二组开始检查;完成修复以后,最后发送第三组验证结果。

动态测试只能针对你拥有或明确获准检查的项目,并且只能在本地或专门的测试环境进行。不得访问真实用户资料、调用真实支付接口或产生真实费用。

第一步:先确认规则,不要扫描

text

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
请先不要修改代码,也不要开始漏洞扫描。

请读取你实际能够访问的项目代码和配置,先告诉我:
1. 你读取了哪些目录、文件类型和配置;
2. 哪些目录、平台后台、云服务或线上设置无法访问;
3. 项目能否在本地或测试环境正常运行。

如果发现密码、令牌或秘密凭证,只报告位置和类型,不得输出完整内容。

然后用不需要安全背景也能理解的语言向我提问,帮我确认:
1. 哪些用户资料、付费额度、管理员权限和高成本功能最需要保护;
2. 访客、免费用户、付费用户和管理员分别可以做什么;
3. 用户资料会经过并保存在哪些地方;
4. 哪些业务规则在重复请求、并发或恶意操作下也不能被打破;
5. 注册、上传、支付和 AI 调用分别有什么次数、额度、并发和成本上限;
6. 哪些风险不在本次检查范围内,哪些风险已经被明确接受。

每次最多问我 5 个最重要的问题。无法从代码确认的内容必须提问;没有答案的定价、权限、额度和限制数字标记为“待定义”,不得自行猜测。

最后生成一份便于我确认的 SECURITY.md 草稿。它是一份写给 AI 和开发者看的产品安全说明书。生成以后停止,等待我确认规则、范围和排除项,不得自动继续扫描。

你应该拿到:一份自己能看懂并且确认过的产品安全规则,以及仍然没有答案的问题清单。

第二步:开始检查,只报告有证据的问题

text

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
请先不要修改代码。

只检查我拥有或明确获授权的项目。需要发送请求、修改测试数据或执行其他动态验证时,只能使用本地或明确获准的测试环境,不得访问真实用户资料、调用真实支付接口或产生真实费用。发现密码、令牌或秘密凭证时,只报告位置和类型,不得输出完整内容。

先说明实际检查的目录、代码、配置、运行环境和版本,以及无法读取或验证的外部系统。如果项目没有成功运行,或者缺少测试账号与测试环境,不得声称完成了动态验证,只能报告代码和配置层面的发现。

然后读取已经由我确认的 SECURITY.md。文件不存在、规则没有确认,或者定价、角色、数据归属、额度和成本上限仍然不清楚时,先停止并列出“待定义”内容,不得自行猜测后宣布通过。

重点检查:
1. 秘密凭证是否进入网页、日志、构建产物、公开配置或历史记录;
2. 在没有共享或其他授权时,用户能否读取、修改或删除别人的资料;
3. 用户能否修改项目编号、价格、余额、角色、权限或任务状态,绕过后台判断;
4. 免费额度、任务提交、扣费、退款和支付通知能否重复生效,重复或乱序通知是否会重复入账;
5. 注册、登录、找回密码、上传和 AI 功能是否缺少次数、并发、用量和总成本限制;
6. 上传文件是否限制类型、大小、数量、处理时间和解压后的体积;
7. 日志、错误信息、分析和监控平台是否泄露凭证、身份令牌或用户资料;
8. 登录会话、管理员后台、共享功能、第三方依赖和部署配置是否存在明显风险;
9. 是否存在注入、XSS、SSRF、CSRF、错误 CORS 等常见 Web 漏洞;
10. 平台后台、数据库权限、文件存储和线上配置是否存在当前无法检查的部分。

报告开头先用非技术语言告诉我,最可能造成用户资料泄露、费用损失或付费绕过的三个问题。

每个确认的问题必须提供:攻击者从哪里开始、经过哪些步骤、最后造成什么影响、对应文件和位置、现有防线、严重程度、最小修复方案和验证方法。注明证据来自代码推断、配置检查、自动化测试还是实际复现。

无法确认的问题标记为“待确认”;无法读取或测试的内容标记为“未验证”并列入覆盖缺口。输出完整覆盖清单,不得把“没有发现问题”写成“产品安全”。

你应该拿到:一份按实际损失排序的问题清单,每个问题都有位置、影响、验证状态和证据。

第三步:修复以后,重新执行原来的测试

text

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
请先不要继续修改代码。现在只验证安全修复是否真的有效。

测试只能在本地或明确获准的测试环境中进行,不得访问真实用户资料、调用真实支付接口或产生真实费用。

先读取原始问题报告、修复前的复现步骤与证据、修复前版本和修复后版本。缺少任何必要材料时,先列出缺失内容,不得猜测原问题已经解决。

对每个问题依次执行:
1. 记录修复前能够成功的攻击步骤和当时结果;
2. 在修复后的版本重新执行同一条路径;
3. 确认系统现在会拒绝非法操作,而不只是页面隐藏了入口或代码看起来发生了变化;
4. 测试相关的正常功能,确认合法用户仍然可以完成原有操作;
5. 根据本次修改范围,检查账号隔离、价格与角色篡改、并发任务、重复扣费和支付通知等相关风险。

验证过程中不要继续修改代码。如果复测失败,只报告失败步骤、实际结果和证据,不要在同一轮再次修复,否则无法判断测试对应的是哪个版本。

最后用表格输出:原问题、修复前结果、修复后结果、正常功能结果、证据位置和最终结论。没有实际执行的项目必须写“未验证”,并列出剩余风险。

你应该拿到:原来的攻击方式已经失效、正常功能仍然可用的实际证据,以及尚未解决或尚未验证的问题。

最后

如果你已经有一个准备上线的产品,今天先做两件事:

  1. 建立两个普通测试账号,在没有共享或其他授权的情况下,确认它们不能互相读取、修改或删除资料。
  2. 把上面的第一组 Prompt 交给能够读取项目的编程 Agent,让它先帮你写清规则和覆盖缺口。确认以后,再按顺序完成检查和复测。

提示词不是安全保证。真正有价值的是实际执行过的测试、留下的证据,以及明确承认还没有检查到的地方。

Vibe Coding 降低了把产品做出来的门槛,没有降低把产品放到公网后的责任。

功能能跑,只能证明它在配合你。

真正要测试的是:当有人不配合时,它还能不能守住用户的数据和你的账单。