在发布 AI 打造的 Next.js + Supabase 应用前,先做这 7 项安全检查
AI 编程助手可以大幅缩短“从想法到可用应用”的时间。但遗憾的是,它并不会缩小应用的攻击面。AI 生成的代码往往看起来没问题,能通过编译,也能跑通正常流程的测试。真正的危险往往藏在代码背后的假设里:谁有权限调用某个接口、哪些凭据被暴露了、某个用户能不能访问另一个用户的数据。
在发布一个 AI 辅助开发的 Next.js + Supabase 应用之前,我会重点检查下面这 7 个方面。
1. 搜索泄露的密钥
首先检查代码仓库和客户端 bundle 里有没有凭据。在 Next.js 中,任何以 NEXT_PUBLIC_ 开头的变量都可能被打包进浏览器端代码。Supabase 的 publishable key 或 anonymous key 本身就是给客户端用的,但 service-role key 绝对不行。要留意这些情况:
- 前端代码里出现了 service-role key
- API 密钥被提交到了代码仓库
- 构建日志或应用日志里打印了密钥
- 环境变量文件被 Git 意外跟踪
- 服务端专用模块被客户端组件引入
密钥一旦暴露,最稳妥的做法是立即轮换(重新生成),而不是简单地把它从最新提交里删掉。Git 历史、构建产物、日志和部署预览里,都还可能留着原来的值。
2. 在服务端验证授权
把按钮藏起来不等于授权。每一个敏感的路由、Server Action 和 API handler,都应该在服务端验证调用者的身份和权限。永远不要因为前端传了一个用户 ID、组织 ID、角色或归属字段,就直接相信它。
危险写法通常是这样的:
const { userId } = await request.json();
const { data } = await supabase
.from("documents")
.select("*")
.eq("user_id", userId);
这里的 userId 是调用者自己传进来的。正确做法是:从经过验证的 session 或 token 中获取身份信息,再用这个可信身份去查询。
3. 用对抗性思维测试行级安全
启用行级安全(Row Level Security,RLS)只是第一步。对于每一张归用户或租户所有的表,至少要测试四种情况:
- 已认证用户可以访问自己的数据行
- 该用户不能访问其他用户的数据行
未认证的请求会被直接拒绝;插入和更新操作也不能把数据的所有权指派给其他人。注意,SELECT、INSERT、UPDATE、DELETE 可能各自需要独立的策略。针对写入操作,既要确认能修改哪些已有行,也要确认允许写入哪些新值。RLS 测试最有价值的问题往往不是「Alice 能不能读到自己的数据?」,而是「Alice 能不能读取或修改 Bob 的数据?」
4. 在每一处边界校验输入
TypeScript 类型在运行时并不存在。请求体、查询参数、Webhook 载荷、上传文件的元数据,以及 AI 输出的结构化数据,在使用之前都要先经过校验。像 Zod 这类 schema 校验库可以帮上忙,但关键在于:把每一个外部传入的值都当作不可信数据看待。
校验不能只检查数据结构,还要落实这些约束:
- 最大长度和集合大小
- 允许的枚举值
- 数值与日期的范围
- 文件类型和大小限制
- 未知字段如何处理
- 业务规则,比如所有权归属、状态流转是否合法
5. 加上滥用防护
即便接口需要登录,也照样可能被滥用。对成本高昂或敏感的操作要加频率限制,比如 AI 生成、登录尝试、邮件发送、文件处理和公开表单。同时还要设置请求体大小上限和超时时间。
面向浏览器的 API 要有意识地配置 CORS:不要把通配符来源与携带凭证的请求搭配使用,也不要拿 CORS 当授权机制——它只能约束那些遵守 CORS 规则的浏览器,起不到真正的鉴权作用。
6. 锁好依赖与 CI/CD 流程
应用本身扫描干净,并不代表交付链路就安全。需要确认以下几点:
- 锁文件(lockfile)已提交,并且在 CI 中使用
- 第三方 CI Action 都固定了版本
- 工作流权限遵循最小权限原则
- 不可信的外部 Pull Request 无法触达部署密钥
- 安全检查任务不能无声无息地失败
- 依赖安装与发布凭证、生产环境凭证相互隔离
- 容器镜像尽量以非 root 用户运行
构建任务会执行依赖里的代码,所以要像对待应用代码一样,把依赖也纳入安全边界。
7. 审查 AI Agent 的权限与指令
Agent 的配置本质上
发布前必须完成的 7 项安全检查
审查仓库指令、工具权限、Hooks、MCP 服务器和自动化命令时,要像审查源代码一样仔细。一个 AI 代理不该因为“这样开发更方便”就拿到生产环境的凭据或破坏性权限。
推荐的做法是:
- 工具访问遵循最小权限原则
- 破坏性操作或外部操作必须显式审批
- 执行环境沙箱化
- 开发和生产凭据严格分离
- 日志必须能对应到具体的 commit 和命令
- 部署前必须有人工审查
一份精简的上线前检查清单
在上线之前,确认以下几点:
- 没有高权限密钥被发送到客户端或提交进仓库
- 每个敏感的服务器操作都验证了身份和授权
- 跨用户、跨租户的访问测试能够安全失败
- 外部输入在运行时经过校验
- 高开销的接口有滥用控制
- CI 任务使用最小权限和隔离的密钥
- AI 代理无法在无人知晓的情况下越权行事
AI 能加快写代码的速度,但它无法替你判断:哪些假设对你的用户和生产环境是安全的。
你在项目里遇到过哪次安全检查,抓到了最意想不到的问题?