AI 构建应用的安全:能承诺的、盲点与防护
了解 AI 构建者能和不能承诺的安全内容、常见盲点在哪里,以及用于安全交付 AI 构建应用的实用防护措施。

本文涵盖内容(以及不涵盖的内容)
“AI 构建的应用”可以指几种不同情况,本文广义使用该术语,包括:
- 大量代码由 LLM 根据提示、规范或工单生成的应用;
- 使用 copilots 来更快地编写、重构和修复代码的团队;
- 可运行工具的 agent 风格工作流(创建 PR、调用 API、查询数据库、部署);
- 将 AI 功能(聊天、摘要、推荐)作为用户体验一部分交付的产品。
目标很直接:在不自称能做到完美安全的前提下,降低风险。AI 可以加速开发和决策,但它也改变了错误发生的方式——以及错误传播的速度。
本文面向谁
本文写给那些没有专职安全团队的创始人、产品负责人和工程团队——或那些有安全支持但需要贴合交付现实的实用指南的人。
你将从本文获得什么
你会了解对“安全保证”可以现实地承诺什么(以及不该承诺什么)、一个可复用的轻量威胁模型,以及当 LLM 涉及代码、依赖、工具和数据时常见的盲点。
你还会看到一些既无聊又有效的防护措施:身份与访问控制、租户隔离、秘密处理、安全部署工作流,以及帮助你及早发现问题的监控和滥用控制。
本文不做什么
这不是合规指南、不能替代安全评审,也不是会自动让任何应用安全的核对清单。安全是人(培训与归属)、流程(审查与发布门)和工具(扫描器、策略、日志)共同承担的。关键是让这种共同责任变得明确且可管理。
安全保证:你能现实地期待什么
关于 AI 构建应用的安全“保证”往往是隐含的而非明确的。团队会听到诸如“模型不会泄露秘密”或“平台是合规的”这样的表述,然后在脑中把它们转化为绝对承诺。这就是期望与现实偏离的来源。
人们常假设的保证
你经常会看到(或推断出)这样的说法:
- 默认安全: 生成的代码会自动遵循最佳实践。
- 代码中无秘密: 密钥/令牌永远不会出现在提示、输出或仓库中。
- 合规: “SOC 2 / ISO / HIPAA 就绪”意味着你的应用合规。
- 数据是私有的: 提示和上传的文件不会被存储或重用。
- 工具使用安全: agent 不会运行危险命令或访问错误的租户。
这些说法有些在特定情况下可能部分为真——但很少是放之四海而皆准的。
为什么保证几乎总是有范围限制
真实的保证有边界:哪些功能、哪些配置、哪些环境、哪些数据路径、以及持续多长时间。例如,“我们不会用你的数据来训练”不同于“我们不会保留它”,两者又不同于“你的管理员不会意外暴露它”。同样,“默认安全”可能适用于入门模板,但不一定适用于经过多次迭代后生成的每一段代码。
一个有用的思路:如果一个保证依赖于你设置正确的开关、以特定方式部署或避免某种集成,那它就不是一个无条件的保证,而是有条件的保证。
安全特性 vs 安全结果
- 特性: 静态/传输加密、SSO、审计日志、秘密扫描。
- 结果: “没有跨租户的数据可访问”、“没有秘密被暴露”、“防止 RCE”。
供应商可以交付特性;而结果仍然依赖于你的威胁模型、配置和运营纪律。
一个简单规则
如果它不可测量,就不是保证。
要求你能验证的东西:书面保留期、文档化的隔离边界、审计日志覆盖范围、渗透测试的范围,以及清晰的责任划分(供应商保障什么,你需要保障什么)。
如果你在使用像 Koder.ai(基于聊天的应用生成,底层有 agent)的“vibe-coding”平台,也要用同样的视角:把“我们为你生成”当作加速,不是安全宣言。关键问题是:哪些部分是标准化且可重复的(模板、部署管道、回滚),哪些部分仍需要你自己的控制(授权、租户范围、秘密、审查门槛)。
AI 构建应用的简单威胁模型
你不需要 40 页的安全文档来做出更好的决策。一个轻量的威胁模型就是一张共享的地图:谁与应用交互、你要保护什么、以及事情可能如何出错——特别是当部分代码和工作流由 AI 生成时。
1) 识别行为者(谁能影响结果)
先列出能制造变更或触发动作的各方:
- 开发者: 编写代码、连接集成、批准 AI 建议的更改。
- AI 工具/agent: 生成代码、调用工具、读取文件、编辑配置。
- 终端用户: 正常使用、边缘输入、账号恢复流程。
- 攻击者: 外部入侵者、被攻破的账号、恶意内部人员。
- 第三方服务: 支付、邮件、分析、存储、身份提供商。
这能让讨论更务实:“哪个行为者能做什么,拥有哪些权限?”
2) 绘制核心资产(你必须保护的东西)
挑出一小套暴露会造成损害的资产:
- 客户数据(PII、文件、消息)
- 凭证与秘密(API 密钥、令牌、签名密钥)
- 源代码与基础设施配置
- 提示和系统指令(常包含业务逻辑)
- 日志与追踪(可能无意间存储敏感输入/输出)
- 模型输出(可能泄露数据或被用来触发操作)
3) 描述典型入口点(风险从哪里进入)
列出输入穿越边界的位置:
- UI 表单与聊天界面
- 公开与内部 API
- Webhooks(经常被过度信任)
- 文件上传(文档、图片、CSV)
- 集成(CRM、工单、网盘、数据库)
4) 可复用的威胁建模检查表(10 分钟)
对每个新功能做这个快速检查:
- 哪些行为者会接触它,最坏的滥用是什么?
- 涉及哪些资产,它们在哪里被存储或缓存?
- 入口点在哪儿,进行了哪些校验?
- AI 工具/agent 具体拥有什么权限?
- 如果攻击者能控制输入(包括提示/文件),会如何?
- 产生了哪些日志,它们是否包含敏感数据?
- 如果出事,回滚计划是什么?
这不能替代完整的安全评审——但能可靠地在改动还便宜时揭露最高风险的假设。
盲点 #1:生成代码质量与不安全默认值
AI 可以快速起草大量可运行代码——但“可运行”不等于“安全”。AI 构建应用中的许多安全故障并非奇技淫巧的攻击;它们是普通的 bug 和不安全的默认设置,因为模型优化的是合理性与速度,而非你组织的安全标准。
生成代码出错的常见方式
认证与授权是常见的失误点。生成的代码可能会:
- 将“已登录”当作“有权限”,跳过角色检查或对象级权限。
- 依赖客户端提供的字段(如
isAdmin: true)而不是服务器端检查。 - 忘记租户范围限定,使用户通过更改 ID 访问其他客户的记录。
输入校验也是常见问题。代码可能只校验常见路径,却漏掉边缘情况(数组与字符串、Unicode 绕过、超大输入)或通过字符串拼接构建 SQL/NoSQL 查询。即便用了 ORM,也可能构建不安全的动态过滤器。
加密误用体现在:
- 自行实现加密而不是使用成熟库。
- 使用过时算法、静态 IV/nonce,或把哈希当成“加密”。
- 在配置文件、日志或前端包里存储秘密。
复制粘贴风险与过时片段
模型常常重现类似公开示例的模式。这意味着你可能得到的代码:
- 过时(使用了具有已知不安全默认值的旧框架版本)。
- 风格上复制自来源不明的例子——缺乏上下文、许可说明或安全加固。
- 缺少“无聊”的部分(限流、CSRF 保护、安全头)——这些在生产环境里保障安全至关重要。
真正能降低风险的防护
从安全模板开始:预先批准的项目骨架,包含你的认证、日志、错误处理和安全默认值。然后对所有安全相关变更(认证流程、权限检查、数据访问层、任何接触秘密的改动)强制人工审查。
再增加不完全依赖人的自动化检查:
- CI 中的 linter 与依赖审计。
- SAST 检测常见不安全模式(注入、不安全反序列化、硬编码秘密)。
- 对运行中的构建做 DAST 或 API 扫描,以抓住静态工具漏掉的问题。
如果你通过 Koder.ai 生成应用(React 前端、Go 后端、PostgreSQL),把模板当作你的契约:一次性把 deny-by-default 的授权、租户范围、安全头和结构化日志内置进去,然后让 AI 在这些边界内工作。同时利用平台能减少运维风险的功能(如快照与回滚),但不要把回滚当成预防措施。
真正重要的测试(并保持它们有效)
安全回归常常以“微小重构”的形式出现。放置一些高杠杆的测试:
- 针对每个角色与敏感端点的授权测试(包括对象级访问)。
- 带恶意载荷和边界情况的输入校验测试。
- 在每次合并时运行的小型安全回归套件——以免模型辅助的改动悄悄撤销昨天的保护。
常见问题
对于 AI 构建的应用,我能现实地声称哪些安全保证?
把任何“保证”都当作有范围限制的声明。问清楚:
- 哪些数据路径在保障范围内(提示、文件、日志、嵌入、备份)?
- 需要开启哪些配置才能让声明成立?
- 保留期是多少,有书面说明吗?
- 责任如何划分(供应商 vs. 你)?
如果你不能测量它(通过日志、策略、文档化的边界),那它就不是一个真正的保证。
安全特性与安全结果有什么区别?
安全特性(SSO、加密、审计日志、秘密扫描)是能力。结果才是你能实际承诺的东西(例如:无跨租户访问、无秘密泄露、无未授权导出)。
只有当特性被:
- 正确配置,
- 应用于正确的系统(包括日志和工具),且
- 持续监控防止配置漂移或回归,
你才可能实现那些安全结果。
如何为 AI 辅助开发创建轻量的威胁模型?
做一个快速的轻量威胁建模:
- 列出参与者(开发者、代理/AI、用户、攻击者、供应商)。
- 列出资产(PII、秘密、代码、提示、日志、模型输出)。
- 列出入口点(聊天/UI、API、Webhook、文件上传、集成)。
- 问:“如果输入被攻击者控制,会怎样?” 尤其是当其能触发工具调用时。
- 为该功能决定回滚/停止机制。
通常这已经足以在改动还便宜时发现最高风险的前提假设。
LLM 生成代码最常见的安全问题是什么?
常见失败往往很普通而非高深莫测:
- 缺失对象级授权(IDOR)和租户隔离。
- 信任客户端提供的字段(例如
isAdmin: true)而非服务器端校验。 - 输入校验薄弱与不安全的查询构造。
- 加密误用(自造加密、错误模式、硬编码密钥)。
缓解方法:使用安全模板、对安全关键代码强制人工审查,并在 CI 中加入自动化检查(SAST/DAST + 目标化授权测试)。
如何在 AI 构建的应用中减少依赖与供应链风险?
从可强制执行的控制开始:
- 用 lockfile 固定版本。
- 在每个 PR 和定期运行依赖扫描(SCA)。
- 在 CI 中生成 SBOM,以便在事件中回答“我们在运行什么?”。
- 在可能的情况下优先使用已签名/验证的制品(镜像、CI actions、发布者)。
同时设定补丁节奏(例如每周;关键 CVE 同日处理),并为每个服务指定命名负责人。
什么是提示注入,如何防止工具被误用?
提示注入是不受信任的内容引导模型去无视你的意图。当模型能使用工具(数据库查询、发邮件、退款、部署)时,风险就会放大。
实用防御:
- 最小权限的工具许可。
- 优先使用白名单化、参数化的操作(例如
lookup_order(id))而非自由形式的动作(任意 SQL/Shell)。 - 在执行前对工具调用做校验(批准域名、最大金额、安全查询模板)。
- 对不可逆或高风险动作要求人工审批。
在 LLM 应用中,除了提示本身之外,隐私泄露还会在哪里发生?
最大的泄露通常来自间接途径:
- 聊天历史/记忆被无限期存储;
- 应用日志和错误跟踪记录原始提示/工具输出;
- APM/追踪默认记录请求体;
- 分析/会话回放工具捕获文本字段;
- 嵌入/向量存储在删除请求时被遗忘。
降低暴露的方法:数据最小化、在记录前积极脱敏、严格的访问控制,并为每个系统记录明确的保留策略(包括备份的可行性)。
在多租户应用中实现租户隔离的最安全方式是什么?
在服务端强制隔离:
- 每个查询都应按
tenant_id进行限定。 tenant_id来源于认证会话,而不是请求体。- 在读/写/删上添加对象级的归属检查。
要做 IDOR 测试:验证用户即便猜到有效 ID 也不能访问其他租户的 /resource/{id}。
在使用 copilots 和 agents 时,我们应该如何处理秘密?
遵循三条规则:
- 不要把秘密放进提示、源码或浏览器中。
- 使用 secrets manager,并在运行时注入秘密。
- 优先使用短期凭证(轮换的 token),并具备快速撤销路径。
在运营上,记录秘密的访问(审计轨迹)、按计划轮换,并在怀疑泄露时立即撤销/轮换。
在上线前我们需要哪些监控和事故准备?
最低限度的生产监控信号:
- 可搜索的审计轨迹,包含认证事件、授权决策、工具调用和数据访问(对敏感字段进行脱敏)。
- 对突发情况的告警:批量读取/导出、重复拒绝、异常工具使用、权限变更。
- 一份运行手册:如何禁用高风险工具、轮换密钥、撤销会话、回滚发布。
如果你不能快速回答“谁用哪个工具对哪些数据做了什么”,事后响应将会缓慢且猜测性强。