OpenAI Codex Security 设计理念解析:为何弃用 SAST 报告作为起点
原文来源:OpenAI Blog
发布时间:2026年3月
关键词:AI 安全、代码安全、SAST、静态分析、Codex Security
引言
数十年来,静态应用安全测试(SAST)一直是安全团队扩展代码审查工作的最有效方式之一。然而,当 OpenAI 构建 Codex Security 时,他们做出了一个深思熟虑的设计选择:不通过导入静态分析报告并让智能体对其进行分类来启动流程。相反,Codex Security 的设计是从代码仓库本身出发——包括其架构、信任边界和预期行为——并在要求人工投入时间之前验证其发现的问题。
这个决策背后的原因很简单:最难发现的漏洞通常不是数据流问题。它们发生在代码看似执行了安全检查,但该检查实际上并不能保证系统所依赖的安全属性时。换句话说,挑战不仅仅是追踪数据如何在程序中流动——而是确定代码中的防御措施是否真正有效。
SAST 的核心局限:过度优化数据流分析
理想化的 SAST 模型
SAST 通常被描述为一个清晰的流水线:
识别不可信输入源 → 追踪数据在程序中的流动 → 标记数据未经净化到达敏感接收点的情况
这是一个优雅的模型,涵盖了大量真实存在的漏洞。
现实中的近似处理
然而在实际应用中,SAST 为了在大规模真实代码库中保持可处理性,不得不进行近似处理——尤其是在存在间接调用、动态分发、回调、反射和重度框架控制流的情况下。这些近似处理并不是对 SAST 的批评;而是在不执行代码的情况下推理代码的现实妥协。
更深层的问题
但这本身并不是 Codex Security 不以 SAST 报告为起点的原因。
更深层的问题是:即使成功地将数据源追踪到接收点,静态分析仍然必须回答一个决定漏洞是否真正存在的问题:
代码中的检查是否真正以系统假设的方式约束了值?
以一个常见模式为例:代码在渲染不可信内容之前调用类似 sanitize_html() 的函数。静态分析器可以看到净化器已运行,但它通常无法确定该净化器对于特定的渲染上下文、模板引擎、编码行为和下游转换是否真正充分。
这就是问题变得棘手的地方。问题不仅仅是数据是否到达接收点,而是代码中的检查是否真正以系统假设的方式约束了值。
换句话说:"代码调用了净化器" 与 "系统是安全的" 之间存在巨大差异。
真实案例:解码前的验证陷阱
场景描述
以下是一个在真实系统中频繁出现的模式:
一个 Web 应用接收 JSON 负载,提取 redirect_url,使用白名单正则表达式验证它,然后进行 URL 解码,并将结果传递给重定向处理器。
经典 SAST 报告视角
传统的源到接收点报告可以描述数据流:
不可信输入 → 正则检查 → URL 解码 → 重定向
真正的问题
但真正的问题不是检查是否存在,而是该检查在后续转换之后是否仍然以重定向处理器解释的方式约束了解码后的 URL。
如果正则表达式在解码之前运行,它是否真的约束了解码后的 URL?
回答这个问题意味着需要推理整个转换链:
- 正则表达式允许什么?
- 解码和规范化如何表现?
- URL 解析如何处理边缘情况?
- 重定向逻辑如何解析方案和权限?
CVE-2024-29041 实例
许多在实践中真正重要的漏洞看起来都是这样的:操作顺序错误、部分规范化、解析歧义、验证与解释之间的不匹配。数据流是可见的,弱点在于约束如何传播——或在转换链中如何失效传播。
这不仅仅是理论模式。在 CVE-2024-29041 中,Express 受到开放式重定向问题的影响,格式错误的 URL 可以绕过常见的白名单实现,因为重定向目标在被编码后又被解释的方式存在问题。数据流是直接的,更难的问题——也是决定漏洞是否存在的问题——是验证在转换链之后是否仍然成立。
Codex Security 的解决方案:从行为出发,然后验证
核心目标
Codex Security 围绕一个简单的目标构建:通过呈现带有更强证据的问题来减少分类工作。
技术实现
在产品中,这意味着使用仓库特定的上下文(包括威胁模型),并在呈现问题之前在隔离环境中验证高信号问题。
当 Codex Security 遇到看起来像是"验证"或"净化"的边界时,它不会将其视为复选框。它会尝试理解代码试图保证什么——然后尝试证伪该保证。
在实践中,这往往表现为以下方式的组合:
| 技术手段 | 描述 |
|---|---|
| 深度代码分析 | 像安全研究员一样阅读相关代码路径,结合完整的仓库上下文,寻找意图与实现之间的不匹配。模型会阅读注释,但不一定相信注释——所以在代码上方添加 //Halvar says: this is not a bug 并不能混淆它,如果确实存在漏洞的话。 |
| 问题切片 | 将问题简化为最小的可测试切片(例如,围绕单个输入的转换管道),以便在没有系统其余部分干扰的情况下进行推理。Codex Security 会提取微小的代码切片,然后为它们编写微模糊测试器。 |
| 跨转换约束推理 | 跨转换推理约束,而不是独立处理每个检查。在适当情况下,这可以形式化为可满足性问题。换句话说,系统为模型提供带有 z3-solver 的 Python 环境,模型擅长在需要时使用它,就像人类在处理特别复杂的输入约束问题时必须做的那样。这对于查看整数溢出或非标准架构上的类似错误特别有用。 |
| 沙箱验证 | 尽可能在沙箱验证环境中执行假设,以区分"这可能是个问题"和"这就是个问题"。没有什么比用调试模式编译的代码进行完整的端到端 PoC 更好的证明了。 |
关键转变
这是关键的转变:不是停留在"存在检查",而是系统推进到"不变式成立(或不成立),这里有证据"。模型会为该任务选择最佳工具。
为何不以 SAST 报告为种子?
合理的疑问
一个合理的反应是:为什么不两者兼顾? 从 SAST 报告开始,然后使用智能体进行更深入的推理。
在某些情况下,预计算的发现是有帮助的——特别是对于狭窄的、已知的错误类别。但对于一个旨在在上下文中发现和验证漏洞的智能体,从 SAST 报告开始会产生三种可预见的失败模式:
失败模式一:过早狭窄化
发现列表是工具已经查看过的地方的地图。如果你将其视为起点,你可能会使系统偏向于在同一区域使用相同的抽象花费不成比例的努力,错过不适合该工具世界观的漏洞类别。
失败模式二:隐含判断难以撤销
许多 SAST 发现编码了关于净化、验证或信任边界的假设。如果这些假设是错误的——或者只是不完整——将它们输入推理循环可能会使智能体从"调查"转变为"确认或驳回",这不是我们希望智能体做的事情。
失败模式三:难以评估推理系统
如果流水线从 SAST 输出开始,就很难将智能体通过自己的分析发现的内容与从其他工具继承的内容分开。如果我们想要准确测量系统的能力,这种分离很重要,而准确测量是系统随时间改进所必需的。
OpenAI 的选择
因此,OpenAI 将 Codex Security 构建为从安全研究开始的地方开始:从代码和系统的意图出发,使用验证来提高置信度门槛,然后再打断人类。
SAST 工具仍然非常重要
适用范围
SAST 工具在其设计的方面可以表现出色:
- ✅ 执行安全编码标准
- ✅ 捕获直接的源到接收点问题
- ✅ 以可预测的权衡大规模检测已知模式
- ✅ 作为纵深防御的强大组成部分
本文的限定范围
这篇文章的范围更窄:它是关于为什么一个旨在推理行为和验证发现的智能体不应该将其工作锚定在静态发现列表上。
超越源到接收点思维
还值得指出纯源到接收点思维的一个相关局限:并非每个漏洞都是数据流问题。许多真实的故障是状态和不变式问题——工作流绕过、授权缺口和"系统处于错误状态"的错误。对于这些类型的错误,受污染的值不会到达单个"危险接收点"。风险在于程序假设将永远为真的东西。
未来展望
OpenAI 期望安全工具生态系统持续改进:静态分析、模糊测试、运行时守卫和智能体工作流都将发挥作用。
Codex Security 希望擅长的部分是对安全团队成本最高的部分:将"这看起来可疑"转变为"这是真实的,这是它失败的方式,这是符合系统意图的修复方案"。
参考资源
总结
| 传统 SAST | Codex Security 方法 |
|---|---|
| 从预定义规则出发 | 从代码行为和意图出发 |
| 关注数据流追踪 | 关注约束传播和验证 |
| 标记潜在问题 | 验证并证明问题 |
| 可能产生大量误报 | 减少分类工作量 |
| 依赖静态近似 | 结合动态验证 |
Codex Security 代表了一种新的 AI 驱动安全分析范式:不是取代人类安全研究员,而是通过提供经过验证的、高置信度的问题发现来增强他们的能力,让他们将宝贵的时间花在真正需要人类判断的地方。
本文基于 OpenAI 官方博客文章翻译整理,如有出入请以原文为准。
本文地址:http://searchkit.cn/article/15774