通过嵌套归纳类型投影验证绕过,在无公理条件下证明 0 = 1。
| 字段 | 值 |
|---|---|
| CVE | CVE-2026-72844 |
| 安全公告 | VulnCheck VCSA |
| 缺陷报告 | leanprover/lean4#14576 |
| 修复 | leanprover/lean4#14577 |
| 影响版本 | Lean 4 ≤ v4.31.0 / nightly ≤ 2026-07-27 |
| 修复版本 | nightly 2026-07-29+ / v4.32.2 |
| CVSS 4.0 | AV:L/AC:L/AT:N/PR:N/UI:P/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N — 6.8 中危 |
| CVSS 3.1 | AV:L/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:N — 6.3 中危 |
| CWE | CWE-843(类型混淆) |
Lean 4 内核不会验证投影表达式中所命名的结构与所投影值的类型是否匹配,并且 src/kernel/inductive.cpp 中的 environment::add_inductive 没有对由辅助类型替换的嵌套归纳类型应用进行类型检查,因此其参数化参数逃逸了检查。
在 Lean 进程中运行的元程序可以注册一个类型错误的嵌套归纳类型,其构造器将 .proj C 0 投影应用于不相关类型 W 的值,内核会在最高内核检查级别下通过常规的已检查 addDecl 路径接受该声明。结果是产生类型混淆,得到一个不携带任何公理的 False 证明,由此可以推导出任何命题——包括 0 = 1。
该漏洞利用:
addDecl 内核路径--trust=0(最大检查)运行#print axioms 报告无公理sorry、unsafeCast、debug.skipKernelTC、FFI 或 .olean 篡改docker build -t lean-cve-poc .
docker run --rm lean-cve-poc
在存在漏洞的 Lean 版本上的预期输出:
[*] Running ZeroEqOne.lean with --trust=0 ...
'bad' does not depend on any axioms
'boom' does not depend on any axioms
'zero_eq_one' does not depend on any axioms
zero_eq_one : 0 = 1
[!] VULNERABILITY CONFIRMED — CVE-2026-72844
zero_eq_one : 0 = 1
Depends on: no axioms
在已修复的 Lean 版本上,内核会拒绝类型错误的归纳类型,脚本会报告该版本不存在漏洞。
任何信任 Lean 内核检查证明作为事实依据的系统都会受到影响。这包括:
根本原因在于内核处理嵌套归纳类型的方式。当消除嵌套出现 I Ds is 时,内核必须验证参数化参数 Ds 与归纳类型声明的参数匹配。存在漏洞的代码未能检查 Ds 中的投影表达式(.proj)是否引用了正确的结构名称——即使当 w : W 且 W ≠ C 时,.proj C 0 w 也会被接受。
结合哈希碰撞(内核在其定义性等式检查中使用 Expr.hash 比较),攻击者可以注册声明,使内核内部的类型分配与实际项语义不一致,从而导致类型混淆和 False 的证明。