Ziren zkVM安全审计:七个月合作与漏洞修复实录

2025年12月中旬,一条消息经由以太坊基金会传到了 Ziren 团队手中。Consensys Diligence 与维也纳工业大学(TU Wien)的研究人员一起,将他们的模糊测试基础设施对准了 Ziren——而且它已经发现了问题。
这个模糊测试工具名为 Arguzz,它通过生成等价程序,并标记虚拟机在处理这些程序时的任何行为差异,来测试零知识虚拟机。它最初针对的是 RISC-V 系统。维也纳工业大学硕士生 Mathias Möller 正在为它构建 MIPS 后端,以验证这套方法是否具有普适性——而 Ziren 这个基于 MIPS32 的 zkVM,顺理成章地成为了目标。原型在后端尚未完成时,就发现了一个 completeness 缺陷。
最初只是一个单独的披露渠道,后来演变成了 Ziren 团队、Consensys Diligence、维也纳工业大学和以太坊基金会之间长达七个月的持续合作:模糊测试共发现五个缺陷——其中四个已修复并经独立复核,一个仍处于开放状态,修复方案正在为 v2.0 进行评估;一个修复已合入 LLVM 上游;一个正式的确定性检查后端已贡献到代码仓库;一轮完整的 Agent 驱动的漏洞挖掘扫描已完成分类并闭环;另外还发布了两版加固版本。本文就是这项工作的记录。

七个月,八个里程碑:从披露渠道开始
为什么要在 zkVM 上做模糊测试
一个 zkVM 有两种比崩溃更重要的失败模式。
Completeness 缺陷意味着一个正确的程序无法执行或证明——系统拒绝了一个本应接受的东西。这类问题烦人、可见,而且实践中通常很快就会被发现。
Soundness 缺陷才是真正危险的那一类:恶意证明者构建出一个看似有效的证明,但对应的执行从未发生过,或者结果本身就是错误的。Soundness 缺陷是无声的。什么都不会崩溃。证明照样能通过验证。对于任何价值和状态都依赖这些证明的系统来说,soundness 就是全部意义所在。
模糊测试同时对这两种模式发起攻击。Arguzz 和它的前身 Circuzz(发表于 CCS 2025;Arguzz 论文将发表于 USENIX Security 2026)会生成电路或程序,通过 metamorphic 变换派生出语义等价的变体,将它们跑过完整流水线——编译、执行、证明、验证——并标记两者之间的任何差异。如果等价的输入在任何阶段产生了不同的行为,那么流水线就有缺陷。在包括 Circom、Jolt、gnark、Noir 和 RISC Zero 在内的八个 ZK 系统中,Consensys 和 TU Wien 的模糊测试工具迄今已发现 59 个主要缺陷,其中 27 个是严重的 soundness 问题。Ziren 于 12 月加入了该计划。

缺陷一:编译器是罪魁祸首
第一份报告在披露渠道开通后一天之内就送达了。使用 MIPS div 指令的自定义内联汇编导致 Ziren 执行器以“不支持的指令”错误发生 panic。这个失败模式诡异得具体:任何两个相等的输入都会触发它,除以 -1 也会触发。
执行轨迹揭示了问题所在。两个输入操作数被分配到了同一个寄存器,这让编译器后续的溢出检查分支变成了寄存器与自身的比较——然后执行落到了一个本不该可达的 BREAK 陷阱上。
问题不在 Ziren 的执行器,而是出在 LLVM 的 MIPS 汇编解析器中——具体来说,是 MipsAsmParser::expandDivRem 在处理扩展除法序列时的寄存器分配逻辑。Ziren 团队对其进行了追踪,向上游提交了报告,并跟进修复直至通过审查(llvm/llvm-project#172967,剩余的效率相关问题在 #174909 中跟踪)。LLVM 补丁于 12 月 23 日合入。新的 Ziren 工具链版本(20260108)在 1 月初发布了该修复,TU Wien 也确认复现案例已解决。
才一个缺陷,这项合作就已经改进了一个应用范围远超 Ziren 的编译器。
缺陷二:规范到底是怎么说的
2 月底,模糊测试工具再次标记了 div——这次是溢出行为。将 i32::MIN 除以 -1 导致执行器以算术溢出错误 panic。MIPS 规范明确指出,div 指令在任何情况下都不会产生算术异常,因此 panic 属于 completeness 违规:一个 ISA 定义为合法的程序却无法被执行或证明。
随后的讨论很好地说明了为什么这类渠道很重要。这是 LLVM 的问题、执行器的问题,还是无人负责的未定义行为?研究人员沿着流水线一步步排查,最终定位了问题:panic 发生在执行器解释一条已经生成的 MIPS 指令时,所以修复应该落在执行器上。
确定的解决方向是使用 wrapping 语义计算商,既符合 MIPS 规范,也与其他同类 zkVM 的做法一致——但事实证明,落实比命名难得多:该问题还与 Rust/LLVM 编译器自身的溢出处理存在交互,目前尚未完全修复。一个完整的修复方案正在为 Ziren v2.0 评估。这是一个 completeness 问题,而不是 soundness 问题:一个合法的程序可能无法完成证明,但绝不可能产生错误的证明。同类问题在 Veridise 对 Ziren 的审计中也曾被指出(V-ZKM-VUL-010,算术溢出)。
缺陷三、四、五:soundness 发现
3 月,报告的性质发生了变化。模糊测试工具不再发现无法运行的程序,而是开始发现本不该存在的证明。
第一个 soundness 问题涉及 teq 指令,它通常用于检查除零。它的约束条件未能充分绑定 rs 寄存器,使得证明者可以在轨迹中的该位置注入任意值。概念验证非常直白:一个计算 gcd(100, 40) 的 guest 程序可以被“证明”返回 123——或者通过环境变量提供的任何其他值——并且生成的证明还能通过验证。修复(ProjectZKM/Ziren#474)约束了寄存器的不可变性,并为相关的选择器列添加了布尔性和 one-hot 约束,同时关闭了 Veridise 的 Picus 工具并行发现的问题。
第二个问题在 3 月中旬出现,落在 ins 指令上。执行 ins a, b, 0, 32——本应完全用另一个寄存器覆盖一个寄存器——却在 ShiftRight 芯片上产生了域外求值不匹配;而一个被修改过的执行器如果执行完全不同的操作,反而能产生有效证明。根本原因是移位量 32 超出了芯片支持的 0 到 31 范围。修复方式是在 ProjectZKM/Ziren#477 中,将该操作拆分为两个分阶段移位。
第三个问题于 4 月 1 日报告,出在 syscall 路径上:存在一个时间窗口,恶意证明者可以在 syscall 执行后、写回 V0 寄存器之前覆盖其返回值。该发现在主分支和预发布分支上都得到了确认,被泛化到 NOP syscall,并与一组相关的 syscall AIR 约束一起关闭(见 ProjectZKM/Ziren#488)。
所有三个修复,以及并行 Picus 分析中得出的约束加固,都被合入了预发布 v1.2.5 分支(ProjectZKM/Ziren#459),随后合入 main 分支。每关闭一个问题,外部模糊测试工具都会针对修复后的分支重新运行一遍——报告、修复、独立重新验证,每个案例都是如此。

第二波:Agent 驱动的挖掘
6 月,合作规模发生了变化。Diligence 运行了 Vulnerability Mining——它专有的 Agent 驱动漏洞发现技术——针对整个 Ziren 代码库,并通过其自助式分类平台 minr 分享了全部输出:按优先级和可利用性排序的候选发现、将数百个原始发现聚类为更少根本原因的实验性根因分析,以及最重要问题的概念验证脚手架。
来自自动化挖掘的候选发现并不等于已确认的缺陷——minr 的意义就在于快速区分两者。Ziren 团队逐一处理队列,修复也很快到位:先是 keccak 海绵初始状态约束(ProjectZKM/Ziren#517),随后是一个整合修复分支,关闭了其余已确认的问题(ProjectZKM/Ziren#519)。两周之内,每个已确认的关键、高危或中危发现都已在分支上有了对应修复。
然后工具开始互相验证。Arguzz 针对挖掘发现生成的 exploit 被用来测试修复分支:每一个 exploit 都被拒绝,guest 程序正常运行。当 Diligence 用之前的扫描结果重新评估 v1.2.6 版本时,21 个发现被确认为已修复——而这次重新评估还捕获了一个新引入的 completeness 回归,它进入了同样的分类-修复循环。这就是按设计运作的流水线:挖掘浮出候选发现,分类确认它们,修复落地,模糊测试重新验证,重新评估捕捉漂移。

这个循环比合作本身更持久:候选不断涌现
还有一个值得注意的细节:Diligence 正在协调其计划中所有 zkVM 团队的发现发布,在所有修复到位之前不会公开披露。Ziren 的修复已经到位。这就是生态系统层面的负责任披露应有的样子。
这改变了什么
具体产出包括:一个上游 LLVM 修复、三个由模糊测试发现并已闭环的 soundness 问题、一个贡献到代码仓库的 Picus 确定性检查后端(ProjectZKM/Ziren#442)、一轮完整的挖掘扫描分类——所有已确认的关键、高危和中危发现均已修复、覆盖 SEXT、TEQ、syscall、keccak 和 memory 路径的加固约束集,以及承载所有这些的 v1.2.5 和 v1.2.6 版本。每个修复都是公开的,每个复现案例都有文档记录,外部研究人员也独立确认了每一个解决方案。
不那么具体的产出同样重要。Ziren 在生产环境中证明真实工作负载,包括保护 GOAT Network 比特币 L2 的桥接基础设施——这正是为什么这类缺陷必须由模糊测试工具在披露渠道中发现,而不是被持有伪造证明的攻击者发现。上述 soundness 发现都是在预发布周期中报告、修复和验证的,那时依赖它们的系统还没有上主网。
这个行业里的安全工作,往往在失败之前都是隐形的。我们认为更好的模式正是这次合作所展示的:拥有专业工具的外部研究人员、一条直达代码所有者工程师的渠道、快速的周转、根因在上游时就把修复提交到上游、互相交叉验证结果的工具,以及工作完成后的公开记录。最初只是一个缺陷报告,现在已经成为一种持续的合作伙伴关系,我们期待这里描述的流水线能继续针对每一个未来版本运行。
我们对 Consensys Diligence 团队的 Tobias Vogel(@T_Birb)、tintinweb(@nicht_tintin)和 Valentin Wüstholz(@vwuestholz)、维也纳工业大学的研究人员,以及以太坊基金会(尤其是 Will Corcoran(@corcoranwill)促成的最初介绍)表示感谢。
还要感谢 Consensys Diligence 的 @NenaRapsody,她对本篇文章的评审和对代码审计一样彻底。
模糊测试工具仍在运行。
ZKM:zkm.io · Consensys Diligence:diligence.security
Ziren(前身为 zkMIPS)是一个基于 MIPS32 的开源、简单、稳定、通用的 zkVM。本文中描述的修复自 v1.2.5 版本起可用,挖掘周期的修复在 v1.2.6 及更高版本中。有兴趣测试 Ziren 的研究人员可以通过 ProjectZKM GitHub 组织联系团队。
- 原文链接: x.com/ProjectZKM/status/...
- 鸿途知科网 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
版权声明
本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。
鸿途知科网
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。