非确定性是CVE修补工作的难题

Hacker News Top 工具

摘要

文章探讨了Claude Mythos、Big Sleep和Microsoft Copilot等AI模型正日益发现CVE漏洞,以及Nix/Flox如何通过依赖集去重,将CVE分类复杂度从O(n)降低到O(u),提供声明式包管理解决方案。

暂无内容
查看原文 导出为 Word 导出为 PDF
查看缓存全文

缓存时间: 2026/05/09 00:31

# 在漏洞不断增加的时代实现 CVE 修复 ource: https://flox.dev/blog/achieving-rapid-cve-remediation-in-an-era-of-escalating-vulnerabilities/ 在 Claude Mythos 公布之前,就有明显的迹象表明,下一个 CVE 时代将由 AI 模型来发现。Big Sleep(https://thehackernews.com/2024/11/googles-ai-tool-big-sleep-finds-zero.html)在 SQLite 中发现了一个零日漏洞,Microsoft Copilot 在引导程序中发现了 20 多个 CVE(https://www.microsoft.com/en-us/security/blog/2025/03/31/analyzing-open-source-bootloaders-finding-vulnerabilities-faster-with-ai/),并且 DARPA 推出了 AIxCC(https://www.darpa.mil/research/programs/ai-cyber)以激励 AI 发现 CVE。 现在,随着 Claude Mythos 等模型的出现,有两个主要要点:随着 AI 模型的改进,我们将看到 CVE 数量的快速增长,同时我们将发现更多跨越多个版本存在、躲避研究人员数十年的 CVE。 最棘手的类别之一是软件包 CVE。大多数组织没有对其堆栈中每个软件包的最新清单。系统级软件包管理器如 `dnf`、`apt` 和 `zypper`,或工具链软件包管理器如 `pip`、`npm` 和 `cargo`,会解析因平台、环境和时间而异的软件包版本。为了确信没有使用易受攻击的依赖项,组织必须手动扫描整个堆栈。再加上 CVE 数量不断增加,这个问题很快变得无法管理。 CVE 的爆发式增长应该鼓励开发者采用已安装软件包的记录系统。这就是我们构建 Flox(https://flox.dev/blog/why-we-built-flox/)的原因:一个面向平台和开发体验团队的开源系统,用于从开发到生产的集中管理环境。Flox 由 Nix 实现,这是一个具有加密可验证依赖图的声明式软件包管理器。Flox 和 Nix 共同改变了模式:不是通过事后扫描来发现易受攻击的软件包,而是在构建时可验证每个依赖项,并可通过 Flox 的记录系统进行追踪。 使用传统软件包管理器,CVE 分诊的规模与您运行的制品、镜像、主机或运行时环境数量成正比。如果您有 *n* 个部署,通常需要对每个部署进行分析,因为无法可靠地证明两个环境包含完全相同的依赖项。 用大 O 表示法表示,这是 O(*n*) 的工作量,而且大部分是冗余的。 Nix 改变了您需要分析的内容。每个 Nix 或 Flox 环境都会解析为用于生成它的完整传递性软件包和构建输入集。用 Nix 的行话说,这被称为"闭包"。闭包是基于输入寻址的,因此如果两个环境解析到相同的 Nix 存储路径,它们可以作为 CVE 分诊的同一单元来处理;您无需独立检查两者来证明它们的依赖项集合相同。 这将分诊变成了去重问题。如果您的 *n* 个环境只共享 *u* 个不同的依赖项集,则昂贵的工作(如检查哪些软件包受到影响或验证补丁)每个依赖项集只运行一次,而不是每个环境运行一次。例如,如果 500 个环境缩减为 50 个唯一的依赖项集,那么分诊工作就不是"扫描 500 个东西",而是更类似于: - 将每个环境映射到其依赖项集。 - 将具有相同依赖项集的环境分组。 - 分析每个唯一的依赖项集一次。 - 为该组中的每个环境重用结果。 用大 O 表示法表示,昂贵的分析从 500 个环境上的 O(*n*) 转变为 50 个唯一依赖项集上的 O(*u*)。 此外,使用 Nix 和 Flox,团队解决两个最耗时的软件包 CVE 问题所需的证据已经记录在 lockfile 中,并在解析后的环境中具体化了。为了识别易受攻击的环境,团队查询哪些 lockfile、闭包或 SBOM 包含受影响的软件包,然后将这些记录映射回使用它们的环境。为了验证修复,他们比较替换图并确认易受攻击的软件包不再存在。 与现状相比,Nix/Flox 工作流程是低容量和低熵的:索引已解析的记录,查询受影响的图,将它们映射回环境,编辑环境定义以选择打了补丁的软件包版本,提升替换环境引用(GitHub 提交、FloxHub 生成),然后将替换图与易受攻击的图进行比较。 诚然,这不是 O(1)。但是——如果说实话——大 O 比较并不是同类比较:现状是耗时的资源密集型检查工作流程,而 Nix/Flox 模型将软件包 CVE 分诊简化为数据库查询、图比较和新环境引用的原子提升。 ## 非确定性和 CVE 非确定性有几个常见来源。对于某些软件包管理器(例如 `apt` 或 `dnf`),相同的安装命令可能会根据其运行的环境、从中拉取的镜像、缓存的内容以及*缓存的时间*产生不同的结果。大多数软件包管理器允许版本范围,使得特定的软件包及其依赖项可能会有不同的解析结果。结果呢?整个堆栈中没有可查询的依赖图记录。 **lockfiles 怎么样?** 传统的 lockfiles 很有用,因为它们可以减少或消除软件包生态系统内的解析器漂移。`Cargo.lock`、`package-lock.json` 或 `uv.lock` 可以记录该生态系统的软件包管理器选择了什么。但 lockfile *不是* 完整运行时环境的声明性、确定性描述:即,组成应用程序、服务或工作负载运行环境的基础镜像、本地库、工具、证书、环境变量和传递性依赖项。 当软件包 CVE 被披露时,组织通常必须跨服务、镜像、主机和运行时环境进行搜索,以确定其暴露程度。易受攻击的软件包可能不是任何人(或任何东西)有意安装的;通常,它是另一个软件包、基础镜像、系统库或特定于运行时的安装步骤引入的传递性依赖项。这就是我们看到的传递性依赖供应链攻击(https://www.lineaje.com/post/axios-npm-breaches-expose-gaps-in-software-supply-chain-attestation)背后的基本逻辑。 在传统工作流程中,这是 O(*n*) 的工作:组织必须独立扫描或分析每个制品,因为没有共享的已解析依赖图来证明哪些制品是等效的。使用 Nix 和 Flox,团队可以将每个环境映射到其已解析的依赖项集(其闭包),并将相同的闭包分组。同样,这个工作流程仍然包括 O(*n*) 的清单步骤,但昂贵的工作转移到 O(*u*),其中 *u* 是唯一闭包的数量。 在这个工作流程中,确定 CVE 事件中的暴露成为一个快速的数据库查询:从受影响的软件包 → 受影响的闭包,然后从闭包到引用它们的环境。 ## 去重 CVE 分诊 当软件由可重现的依赖项集构建时,CVE 分诊不再需要从独立扫描每个制品开始。相反,每个运行时可以映射到构建它所需的已解析依赖项集:其闭包、软件包元数据、SBOM 或等效的依赖项记录。 通过维护良好的依赖项索引,暴露查询可以从 CVE 受影响的软件包快速查找到受影响的依赖项集,然后从这些集查找到引用它们的环境。 ### Nix 如何实现确定性? Nix 通过颠覆我们用于构建、打包和使用软件的传统模型来实现确定性。大多数软件包管理器将预构建的制品安装到全局可变的系统上下文中,使得*最终环境*——制品运行所处的上下文——由 (a) 上游仓库和镜像的状态、(b) 主机本身的状态以及 (c) 所有其他环境输入决定。 Nix 采取相反的方法:它从声明的输入构建软件包,并将它们持久化到不可变的存储路径中。如果使用缓存中的预构建二进制替代品,这仍然对应于哈希过的 Nix 存储路径。这就是关键:*Nix 不将下载的二进制文件视为任意软件包*;它将它们视为具有声明输入的已知构建过程的输出。 这个模型使依赖图可查询。Nix 构建输出位于不可变的存储路径中,每个输出都嵌入其完整的传递性依赖图:软件包、它的依赖项,以及那些依赖项的依赖项。(同样,这是它的"闭包")生成的环境可以进行检查、去重和重用,用于 CVE 分诊,将分析单元从"这个主机或镜像上碰巧安装了什么?"转变为"哪些已解析的依赖图包含易受攻击的软件包?" Nix 构建是**密封的**,因为它们与主机的环境状态隔离。给定相同的声明输入,Nix 可靠地计算相同的派生和存储路径。Nix 输出也是可验证的。Nix 存储中的每个软件包都可以通过基于其输入的加密哈希来识别。 您可能对 Nix 和 Flox 之间的实际区别感到好奇。Nix 提供了使可重现环境成为可能的软件包模型、构建系统和存储语义。Flox 基于 Nix 构建,将这些原语转化为团队的完整软件生命周期工作流程:创建环境、安装和更新软件包、跨机器激活环境等。Flox CLI 公开了熟悉的软件包管理器命令,如 `install`、`list`、`uninstall` 和 `activate`,因此用户可以在不编写 Nix 表达式或 flake 的情况下使用 Nix。Flox 还增加了经过审核的软件包目录、声明式环境清单和通过 FloxHub 的集中式版本化共享。 ### 从清单到已解析的依赖图 Flox 清单不是安装脚本:它是环境的声明性描述:Flox 将在运行时实现的软件包、变量、钩子和服务。当 Flox 解析该清单时,它将结果写入一个名为 `manifest.lock` 的文件。将此 lockfile 视为 CVE 分诊的基础:它记录了 Flox 解析器选择的软件包版本、源修订版、派生、目标系统和 Nix 存储输出。这些存储输出是追踪环境的传递性依赖图的起点:已解析的软件包、它们的运行时依赖项、这些依赖项的依赖项。该图可以进行检查、索引、扫描 CVE 暴露或用于创建 SBOM。 对于审计和 CVE 工作流程,这给了团队比安装脚本或事后扫描器结果更强的东西。清单步骤仍然是 O(*n*):每个环境都必须映射到它实际使用的已解析依赖项记录,如 `manifest.lock`、FloxHub 生成、闭包指纹或 SBOM。但这个步骤主要是记账工作。昂贵的工作在于解析这些记录背后的依赖图——**Nix 和 Flox 默认执行的工作**。 剩余的 CVE 具体工作是 (1) 将这些图与已知漏洞数据进行索引,(2) 对等效环境进行去重,(3) 验证给定的 CVE 是否实际适用。一旦环境按相同的 lockfile 或闭包分组,该工作就从每个环境上的 O(*n*) 转移到唯一已解析依赖项集数量上的 O(*u*)。如果 500 个环境缩减为 50 个唯一的 lockfile 或闭包,则昂贵分析运行 50 次而不是 500 次。 ### 修复也是去重 同样的模型适用于修复。FloxHub 为单个软件包和完整环境生成 SBOM,因此组织拥有每个环境生成的已解析依赖图。当他们将这些 SBOM 与漏洞数据进行索引时,确定漏洞暴露就变成了查询数据库的问题:哪些已解析的图包含受 CVE 影响的软件包,哪些环境或 FloxHub 生成引用这些图?注意:这在原则上并非 FloxHub 独有。Nix 用户可以手动完成底层工作:给定一个存储输出,他们可以遍历闭包,检查它包含的软件包和库,并从该图生成 SBOM。 从那里,团队更新相关的软件包或输入,重新生成 lockfile,(如果使用 Flox 和 FloxHub)发布一个新的环境生成。修复问题变得非常具体:新的 lockfile 是否解析为易受攻击软件包的更新版本,以及生成的依赖图是否不再包含易受攻击的软件包输出? 不,这不是 O(1) 的修复。团队仍然需要测试运行时环境的行为,协调推广,并提升替换的 FloxHub 生成。但在这个模型中,您只需识别受影响的图一次,验证替换图一次,并在使用易受攻击图的任何地方提升该替换。此重用适用于 Flox/Nix 环境捕获的依赖项;在激活或运行时强制获取的软件包或制品必须单独固定和跟踪。由于 Flox 和 Nix 保证可重现的输出(https://flox.dev/blog/reproducible-builds-made-simple-with-nix-and-flox/),修复 CVE 就像在 `manifest.lock` 中定位依赖项、调整 `manifest.toml` 并重新锁定、重新构建,然后重新部署到任何受影响的環境一样简单。因为构建是完全确定性的:如果它在本地有效,在生产环境中也会有效。 ## 为什么这没有成为常态? Nix 是一个与 `dnf`、`apt`、`brew` 等流行项目非常不同的软件包管理器。 主要原因是价值观的差异。大多数软件包管理器重视便利性和快速构建时间。Nix 重视密封性,而密封性相当昂贵。一切都在隔离中构建;即使有缓存副本,这也意味着更长的构建时间和更多的磁盘空间。 今天,我们生活在不同的时代。磁盘空间不再那么稀缺,我们有充足的互联网带宽。与 AI 系统的需求相比,Nix 的资源要求相当微不足道。钟摆可能从优先考虑高效的构建时间转向优先考虑高效的修复时间,特别是随着 AI 代理推动 CVE 数量的增加。 我们并非不知道许多开发者害怕软件包管理器重构。值得庆幸的是,我们相信借助编码代理,过渡在未来不会那么艰巨,但我们仍在研究该方法的最佳路径。 ## 编码代理:(有点)好和(非常)坏 O(*n*) 和 O(*u*) 的比较在编码代理的世界中可能看起来微不足道。我们生活的时代是 Claude Code 正在对数百个文件运行 `grep` 来更改按钮的 `border-radius`。 在基础设施层面,这有点不同。是的,一个组织可以构建一个代理来常规检查代码库、收集依赖项并将它们与新出现的 CVE 进行比较。随着模型变得更智能,O(*n*) 扫描问题*可能*会在编码代理的混乱中消失。然而,这是一种短视的思考问题的方式。对于 AI 代理实现自主扫描,它需要访问每个节点,无错误地运行,并为每个 CVE 运行数百次搜索。它*可能*能够常规地做到这一点而不出错,但这是一个"差不多就行"的借口,而不是良好的安全措施。同时,对于 Flox,有一个可以轻松处理的单一事实来源。 编码代理也会带来自己的安全挑战。 系统提示中的敏感信息可能被恶意提取。代理需要谨慎处理敏感数据和系统级访问权限,以防止潜在的安全漏洞。授权边界必须严格定义,防止未经授权的系统操作和潜在的攻击向量。 Flox 通过提供明确的环境隔离和声明性上下文来解决这些挑战。它确保代理只能访问明确授权的资源,通过清单限制操作范围。 这种方法将传统的扫描模式转变为更智能的依赖项和上下文管理。 Flox 的关键优势在于其精确的变更追踪能力。它不仅仅是简单地列出变更,而是详细记录每个组件的具体版本变化,提供无与伦比的可追溯性。 这种方法从根本上改变了处理复杂 CVE 的方式,将看似无穷无尽的工作转化为可管理的有限集合,显著降低了安全维护的复杂性。 凭借完全确定性的保证,组织可以系统地识别、修复和推广受影响的环境,从而将安全响应从被动防御转变为主动精准的修复过程。 修复 CVE 现在变成了一项精确、可控的任务,每个受影响的图只需一次有针对性的验证,就能确保整个基础设施的安全性和一致性。

相似文章

零日漏洞的倒计时

Lobsters Hottest

Mozilla 利用 Anthropic 的 Claude Mythos Preview AI,在 Firefox 150 中找出并修复了 271 个零日漏洞,标志着网络安全格局的重大转变:AI 让防御者首次能够彻底甩开攻击者。

Anthropic Claude Code 泄露揭示严重命令注入漏洞

Lobsters Hottest

在 Anthropic 的 Claude Code CLI 和 SDK 中发现了严重命令注入漏洞(CVE-2026-35022,CVSS 9.8),攻击者能够通过环境变量、文件路径和身份验证助手执行任意命令并窃取凭据。这些缺陷使得在 CI/CD 环境中能够进行毒化流水线执行攻击,需要立即修补和配置更改。

网络安全现在看起来像工作量证明

Simon Willison's Blog

英国AI Safety Institute对Claude Mythos的评估表明,人工智能驱动的安全漏洞检测创造了一种新的经济模式,其中网络安全变成了一场代币消耗竞赛,激励对安全审查的持续投资,并使开源库作为共享安全基础设施更有价值。