非安全问题:curl披露政策过滤AI扫描结果Not a Security Issue
本文介绍curl项目如何通过其披露政策有效过滤掉来自AI安全扫描工具的误报或低风险漏洞报告。文章详细说明了curl团队如何建立自动化流程,在接收外部漏洞信息时进行初步筛选,仅将高严重性、可验证的问题提交给官方渠道。这种做法既保障了开源项目的安全响应效率,又避免了社区被大量噪音干扰。该机制为其他开源项目处理第三方安全情报提供了参考范例。
Andrew Nesbitt
丹尼尔·斯坦伯格昨天提到 Mythos 发现了一个真实的 curl 漏洞,这让我用几个 AI 辅助扫描器在 curl 代码库中探查了一番——毕竟这个代码库已经被各种模糊测试工具和审计人员彻底检查过了。结果比预期要好,其中一个原因尤为突出:这些扫描器读取了 docs/VULN-DISCLOSURE-POLICY.md 文件,并据此进行了处理。
一类结果被标记为“真实缺陷,值得修复,但根据项目自身政策不构成安全问题”:例如由服务器触发的空指针解引用、小型内存泄漏,或仅在用户已能控制命令行参数时才会触发的问题。工具发现了这些问题,对照 curl 公开的“不计入安全范畴”清单进行核查后,在我动手处理前就自动降级了它们。
被降级的案例之一:扫描器发现 tool_formparse.c 在处理 -F 表单参数构成的链表时会递归遍历且无深度限制,于是构造了一个长达 15 万行的配置文件来复现问题,最终触发 ASan 堆栈溢出。它在总结中写道:“触发条件需用户以攻击者提供的配置或参数运行 curl,因此按政策排除”,并将其归类为质量类缺陷后继续扫描。另一个 LDAP 错误路径上的小 ber_free 内存泄漏也得到类似处理,仅标注“政策排除小型内存泄漏”。相比那些没有书面政策的开源项目,此次扫描的噪音水平明显更低。
过去几个月里几乎所有关于 AI 生成安全报告的文章都在讨论收到报告后的应对措施。丹尼尔对此已有详尽论述,赛斯·拉森早在 Python 社区就提出过相关观点,ISC 在某平台上报告了高达 89% 的误报率,OpenSSF 也正在组建工作组收集分类实践。这些工作都聚焦于接收端,而本次 curl 的扫描结果表明:帮助人工分类员理解规则的同类文档,也可以加载进扫描器的上下文环境中,在任何人阅读前就抑制住相关发现。
代理式扫描器在遍历仓库过程中会主动拉取 SECURITY.md、CONTRIBUTING.md 等疑似政策文件,因为它们基于与编程助手相同的架构构建。维护者无法控制谁将扫描器指向该仓库,但当扫描器到达时,仓库内存在的文件完全属于其所有者。
VULN-DISCLOSURE-POLICY.md
实际起作用的章节标题为“非安全问题”,列出了十六个具体类别,涵盖小型内存泄漏、永不终止的传输、恶意服务器触发的 NULL 解引用、最终会结束的忙循环、终端输出中的转义序列、协议必需的弱算法,以及任何依赖诱导用户执行特制命令行的行为。
每个条目都配有说明段落:其中关于忙循环的解释指出,应用程序本就需要正常处理持续占用 100% CPU 的传输循环,因此长时间占用属于缺陷而非漏洞;而命令行列出的理由则是,若攻击者能让你执行特制 curl 调用,那他同样能让你执行 sudo rm -rf / 这类危险操作。
正是这些说明文字让人类或机器读者能够将规则应用于未明确列出的情况,而这些分类之所以有效,正是因为它们针对的是 curl 这一特定场景。一条泛泛的“DoS 不在范围内”声明并无助益,但“永不终止的传输不是安全问题,因为应用本就需对连接停滞采取防护措施”这类表述,才是可被工具匹配发现的。
Prior art
Node.js 在 SECURITY.md 中嵌入了一个完整的威胁模型,明确划定了信任边界,列出了运行时不信任的内容(如通过 API 打开的文件内容、入站网络数据),以及它所信任的内容(如操作系统、开发者自己的代码),并通过要求非对称资源消耗来对 DoS 报告设置高标准,同时排除任何可通过常规进程回收缓解的问题。
Django 的政策提供了“不被视为有效”的报告示例,主要是将未经过滤的输入传递给内部函数并归咎于该函数的变体。它还要求报告者不要包含 CVSS 评分、严重性评估或“冗长的背景说明”,这实际上是对 LLM 默认输出内容的相当直接的描述。
Chrome 的安全 FAQ 是该类别中最常被引用的单一排除项来源,即物理本地攻击者若已能像你一样运行代码,则不在范围内,因为浏览器无法防御操作系统。
我收集了大约五百个发布某种威胁模型文件的仓库。文件名五花八门,有 THREAT-MODEL.md、threat_model.md、ThreatModel.md,有时还藏在 docs/ 目录的三层子目录下,这意味着工具必须主动搜索,而不能仅检查已知路径。
OpenSSF 的 SECURITY-INSIGHTS 模式已有漏洞报告中的 in-scope 和 out-of-scope 数组机制,已有几年历史,这显然是这类信息的机器可读存储位置,但我尚未见过能消费这些数据的扫描器。
写什么
基础是至少拥有一个 SECURITY.md 文件,令人惊讶的是,许多广泛依赖的仓库仍缺乏此文件;同时在 GitHub 上开启私有漏洞报告功能,以便报告能提交到一个非公开渠道。即使是一个空的策略文件附带联系方式,也比没有强,因为这是人类和工具都会首先查找的地方。
排除列表是便宜的部分,也是 curl 扫描中完成工作的部分。每个条目需要包含模式名称、一个明确的声明(不符合条件)以及足够的理由,使规则能推广到你所写的具体案例之外。
在此基础上,还需一个简短的威胁模型,描述攻击者被假定为谁、控制什么,以及项目实际要保护的对象——对大多数项目而言,三到四段即可涵盖。排除列表本质上只是将威胁模型重述为具体案例。实践中,大多数维护者会先写排除项,因为那里是痛点所在,随着错误报告的积累逐步添加条目,最后才写下解释为何这些条目成立的那部分模型,这样也可以,尽管一旦模型存在,列表往往会变得更清晰。CNCF 自评模板是一个合理的起点。
值得添加的一个类别是我尚未见过的:文档与行为不匹配。AI 扫描器频繁标记此类问题,因为“文档说 X,代码做 Y”是他们学到的发现模板,技术上确实算缺陷,但只有当所记录的行为是某人依赖的安全保障时,才构成安全问题。文档声明出错时返回 null 却实际抛出异常的函数应列入公共追踪器;而文档称会转义 HTML 但实际不会的函数则属于真实漏洞。
在策略文件中明确区分这一点本可以进一步减少 curl 的结果,Piotr Karwasz 也从 Log4j 的角度提出了几乎相同的观察:大多数边界情况报告描述的是威胁模型已排除的真实行为,而修复通常只是在 Javadoc 中添加一行说明参数是否可信。
但这并不能阻止有人不读任何内容就将一个虚构的缓冲区溢出漏洞粘贴到你的 HackerOne 队列中,而且报告质量分布的底部是文档无法触及的。但那些设计更完善的工具——在报告前会读取仓库的工具——正是策略文件能够引导的对象,而如今越来越多的扫描工作正由这类工具完成。将威胁模型写下来一直是人类报告者的良好实践,结果发现新的读者比旧工具更字面化地遵循它。
无论接下来出现什么神话般的模型,它们都会读取相同的文件。
需要完整排版与评论请前往来源站点阅读。