我们的 AI 引擎 Neutron 在加州大学伯克利分校的 CyberGym 基准测试中取得了 97.1% 的成绩。 了解更多

深度解析

深度解析

Wasmtime 编译错误导致沙箱逃逸(CVE-2026-115889)

CVE-2026-115889 是严重的 Wasmtime 沙箱逃逸漏洞:Cranelift 将索引打包进 24 位字段,特制模块可使其溢出。已在 36.0.19 和 43.0.0 中修复。

要点速览

  • Wasmtime 使用自身的编译器后端 Cranelift 编译 WebAssembly。在编译器中间表示中,每个值记录将指令、块或值索引打包进一个 64 位字中的 24 位字段,而保护检查仅在调试构建中触发 panic。
  • 如果 Wasm 函数使任一指令、块或值索引超过 2^24 - 1,约 1670 万,就会在发布构建中溢出 24 位字段。它可以是一个真正巨大的函数,也可以是刻意构造以膨胀计数的函数。该值随后引用错误的指令、块或值。编译器根据这些受损数据生成机器码,结果可能是类型混淆,即沙箱逃逸。
  • Bytecode Alliance 将此漏洞评为严重,CVSS v3.1 为 9.9,任何架构上默认的 Cranelift 后端都受影响。主线自 Wasmtime 43.0.0(2026 年 3 月)起已修复;36.x 维护线在 2026 年 10 月 19 日发布的 36.0.19 中获得回移修复,公告也于同日发布。
  • 在 36.x 线上升级至 36.0.19 或更高版本。在主线上,43.0.0 仅修复 CVE-2026-115889;要消除下述全部三个漏洞,请运行 48.0.7 或更高版本,或在 49 线上运行 49.0.4 或更高版本。截至 2026 年 10 月 24 日,没有已知在野利用。
  • 同一 10 月窗口还出现了两个伴随沙箱逃逸漏洞。CVE-2026-115893 让含有超过约 256,000 个目标的 br_table 在 aarch64 上跳转到攻击者选择的偏移;已在 36.0.19、48.0.7 和 49.0.4 中修复。GHSA-m9f7-9w4p-gv38 让客户代码在 macOS 和 FreeBSD 上通过符号链接重命名,将任意宿主目录移入自身沙箱;已在 36.0.18、48.0.6 和 49.0.3 中修复。

我是否受影响?

如果以下条件全部成立,您就受影响:

  • 您运行 Wasmtime 或内嵌它的产品,并使用默认的 Cranelift 编译器后端。
  • 版本为 36.x 维护线中早于 36.0.19 的版本,或主线上的 37.0.0 至 42.x。
  • 客户 Wasm 模块并非完全可信:它们来自租户、用户或其他各方,您对其代码采取的是限制而非信任。

公告对影响的说明很明确:“在任何架构/平台上,采用默认设置(使用 Cranelift 后端)的 Wasmtime 引擎都可能因特制 Wasm 模块发生沙箱逃逸。”仅运行第一方可信模块的引擎不会暴露于此漏洞。

2026 年 10 月的公告窗口还包含两个受影响范围不同的沙箱逃逸漏洞,因此下表分别列出每个漏洞:

漏洞 受影响版本 修复版本
CVE-2026-115889,任何架构 36.x:早于 36.0.19;主线:37.0.0 – 42.x 36.0.19 和 43.0.0(主线,2026 年 3 月)
CVE-2026-115893,仅 aarch64 36.x:早于 36.0.19;主线:37.0.0 – 48.0.6 和 49.0.0 – 49.0.3 36.0.19、48.0.7 和 49.0.4(均发布于 2026 年 10 月 19 日)
GHSA-m9f7-9w4p-gv38,macOS 和 FreeBSD 上的 wasmtime-wasi 36.x:36.0.17 及更早版本;主线:37.0.0 – 48.0.5 和 49.0.0 – 49.0.2 36.0.18、48.0.6 和 49.0.3(均发布于 2026 年 10 月 14 日)

aarch64 公告指出,所有支持 aarch64 的 Wasmtime 版本都受 CVE-2026-115893 影响,可追溯到 v1.0 之前于 2020 年首次加入支持时。文件系统公告要求客户代码对沙箱内某目录具有写权限,且宿主运行 macOS 或 FreeBSD;Linux 和 Windows 宿主不受影响,因为它们的 renameat 不会跟随带尾部斜杠的符号链接。

检查您运行的版本:

# CLI version
wasmtime --version

# Rust dependency tree
cargo tree -i wasmtime -e features | head
cargo tree --depth 1 | grep wasmtime

# Docker image check
docker run --rm <your-image> wasmtime --version

Wasmtime 通常被内嵌使用,而非作为 CLI 运行:请检查平台依赖树中的版本,因为无服务器和插件平台通常会固定其版本。

如何修复?

升级 Wasmtime。要一次消除全部三个漏洞,最低修复版本分别为 36.x 线的 36.0.19、48 线的 48.0.7 和 49 线的 49.0.4:

# Rust, 36.x maintenance line
cargo update -p wasmtime --precise 36.0.19
# Rust, 48 line
cargo update -p wasmtime --precise 48.0.7
# Rust, 49 line
cargo update -p wasmtime --precise 49.0.4

# CLI install script (installs the latest release)
curl https://wasmtime.dev/install.sh -sSf | bash

43.0.0 仅修复 CVE-2026-115889。43.0.0 至 48.0.6 和 49.0.0 至 49.0.3 仍含 aarch64 br_table 逃逸漏洞。43.0.0 至 48.0.5 和 49.0.0 至 49.0.2 仍含文件系统逃逸漏洞。

公告没有列出临时解决方案。在编译前拒绝异常大的函数体,可以缩小能够触发溢出的输入范围,但并非修复。公告将特制以使用大量 SSA 值的函数,与函数体非常大的情况分别列出,因此字节大小上限并不是可靠边界。应将引擎升级作为修复,将任何大小限制仅作为权宜之计。

使用 Ostorlab 扫描 Rust 仓库和容器镜像,标记所有仍固定使用早于 36.0.19、48.0.7 或 49.0.4 的 wasmtime 版本的构建。

根本原因是什么?

Cranelift 的中间表示使用 ValueDataPacked 记录跟踪每个 SSA 值。为了将记录保持为 64 位,编译器把四个字段打包进一个字:2 位标签、14 位类型,以及名为 x 和 y 的两个 24 位字段。

y 字段保存定义指令的索引、块索引,或别名所对应原始值的索引。它们随函数大小增长。对于指令结果和块参数,x 仅保存输出序号或参数序号,因此保持较小。对于优化器创建的 union 节点,两个字段都保存值索引。受影响源码中的布局如下:

// cranelift/codegen/src/ir/dfg.rs (before the fix)
//        | tag:2 |  type:14        |    x:24       | y:24          |
//
// Inst       00     ty               inst output     inst index
// Param      01     ty               blockparam num  block index
// Alias      10     ty               0               value index
// Union      11     ty               first value     second value

打包辅助函数仅使用调试断言保护字段宽度,该检查在发布构建时会被编译掉:

// cranelift/codegen/src/ir/dfg.rs (before the fix)
fn encode_narrow_field(x: u32, bits: u8) -> u32 {
    let max = (1 << bits) - 1;
    if x == 0xffff_ffff {
        max
    } else {
        debug_assert!(
            x < max,
            "{x} does not fit into {bits} bits (must be less than {max} to \
             allow for a 0xffffffff sentinel)"
        );
        x
    }
}

断言消失后,encode_narrow_field 原样返回索引。打包代码将其移位到相应位置,未经掩码处理便按位或入字中,因此第 24 位以上的位会溢入相邻字段。读回记录时,每个字段都被掩码限制为 24 位。y 中值为 2^24 的指令索引读回后变成 0,即完全不同的指令,同时还会破坏 x。

一句话概括:编译器数据结构把实体索引存入宽度不足的字段,而唯一的溢出检查会被发布构建删除,因此值数量足够多的函数,会在代码生成开始前破坏编译器自身的值到定义映射。

后果是受攻击者影响的错误编译。声称自己由错误指令定义的 Value,会继承该指令的结果类型和语义。随后编译器生成的机器码会将一个操作的输出按另一种类型消费:客户代码内的已编译代码发生类型混淆,破坏 Wasmtime 本应强制实施的沙箱。

如何利用?

攻击者提供一个 Wasm 模块,其中某函数使 Cranelift 的指令、块或值索引超过 2^24 - 1。在发布构建中,索引静默回绕,错误编译且类型混淆的代码以宿主权限运行。截至 2026 年 10 月 24 日,没有公开概念验证,也没有已知在野利用。根据公告和补丁,路径如下:

  1. 攻击者能够向引擎提供 Wasm 模块:部署代码的租户、上传插件的用户,或任何客户模块作者。这就是 CVSS v3.1 向量将所需权限记为低的原因。
  2. 模块包含一个函数,使指令、块或值索引超过 2^24 减 1,约 1670 万。公告列出两种形式:非常大的 Wasm 函数体,或专门构造以使用大量 SSA 值的函数。
  3. 在转换为 Cranelift IR 和优化期间,指令、块或值索引超过 24 位字段。在发布构建中不会触发 panic;打包记录静默地别名到其他索引。
  4. 优化器和后端读取受损映射。一个值解析到错误定义,带有错误类型,生成的机器码执行验证器从未看到的操作:例如,将整数位重新解释为引用或另一种类型的值。
  5. 在客户模块内部,攻击者使用类型混淆的代码读写 Wasm 线性内存边界之外的位置,或触达沙箱本应隔离的宿主机制:实现沙箱逃逸,以宿主进程权限运行。

整个攻击只需一个已编译模块。无需滥用宿主 API,无需引擎配置错误,也无需第二个漏洞。

特制模块如何从溢出发展到逃逸?

flowchart LR A["攻击者提供 Wasm 函数,
索引超过 2^24 - 1"] --> B["Cranelift 将索引打包进
一个 u64 的 24 位字段"] B --> C["发布构建:仅调试存在的检查
被删除,溢出静默发生"] C --> D["值记录错误地指向
其他指令或块"] D --> E["后端根据受损的
值类型信息生成代码"] E --> F["客户模块内的类型混淆
突破 Wasm 沙箱"]

失效的检查位于 C:唯一的溢出保护在发布构建中不存在。

攻击者能做什么?

逃出 WebAssembly 沙箱,并以宿主进程权限执行代码。Wasmtime 的安全模型将客户代码视为不可信:沙箱逃逸意味着客户代码直接触达宿主内存、宿主 API 和进程能力。CVSS v3.1 向量 AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H 对机密性、完整性和可用性均评为高影响,并包含范围变化,与客户模块攻陷宿主的情形相符。

攻击所需条件:

  • 使用默认 Cranelift 后端的 Wasmtime,任意架构,发布构建。
  • 受影响版本:36.x 线上早于 36.0.19,或 37.0.0 至 42.x。
  • 攻击者代码必须实际由引擎编译,因此仅预编译可信模块或使用其他后端的引擎不在已演示路径内。

两个伴随沙箱逃逸漏洞是什么?

同一 10 月公告窗口还有两个 Wasmtime 沙箱逃逸漏洞,分别发布于 2026 年 10 月 19 日和 10 月 14 日,修复版本均与 CVE-2026-115889 不同。

CVE-2026-115893:大型 br_table 如何在 aarch64 上逃出沙箱?

在 aarch64 后端,若 Wasm 模块的一条 br_table 指令包含超过约 256,000 个目标,就会被编译为目标错误的条件分支。该分支可跳转到模块控制的偏移上的任意代码,公告指出,这可导致任意沙箱逃逸。

所有支持 aarch64 的 Wasmtime 版本都受影响,可追溯到 v1.0 之前的 2020 年初始支持。修复于 2026 年 10 月 19 日随 36.0.19、48.0.7 和 49.0.4 发布。主线 43.0.0 至 48.0.6 修复了 CVE-2026-115889,但仍含此漏洞。

GHSA-m9f7-9w4p-gv38:符号链接重命名如何逃出文件系统沙箱?

在 wasmtime-wasi crate 中,客户模块可将进程能够访问的任意宿主目录移入自身沙箱,然后读写它。

重命名时,wasmtime-wasi 从源路径去除尾部斜杠,以解析其父目录。随后在调用 renameat 前重新附加斜杠。客户模块创建一个指向沙箱外部的相对符号链接,例如 symlink("../outside", "up"),并将 "up/" 重命名到沙箱中。宿主内核跟随符号链接,将外部目录移入。早先的 GHSA-vqjp-4c8c-hfgg 修复改变的是路径打开方式,而非重命名方式。

macOS 和 FreeBSD 宿主受影响。Linux 和 Windows 不受影响,因为它们的 renameat 不会跟随带尾部斜杠的符号链接。客户模块需要对沙箱内某目录具有写权限。修复于 2026 年 10 月 14 日随 36.0.18、48.0.6 和 49.0.3 发布。没有已知临时解决方案,也没有分配 CVE。

这两个伴随公告均未报告在野利用。

修复为什么有效?

修复移除了窄字段:x 和 y 变为完整的 u32 索引,因此任何函数大小都不会让索引回绕到另一项定义。在主线上,拉取请求 #12613(2026 年 2 月 18 日合并,随 Wasmtime 43.0.0 发布)将打包 u64 替换为:

// cranelift/codegen/src/ir/dfg.rs (after the fix)
-struct ValueDataPacked(u64);
+#[repr(Rust, packed)]
+struct ValueDataPacked {
+    x: u32,
+    y: u32,
+    flags_and_type: u16,
 }

布局注释从 x:24 | y:24 变为 x:32 | y:32:两个字段现在都能保存完整 u32 范围,encode_narrow_field 和 decode_narrow_field 辅助函数被删除,因为不再需要缩窄。记录从 8 字节增至 10 字节。该 PR 的基准测试仍测得编译时间改善了百分之 3 至 5。

36.0.19 回移补丁,即拉取请求 #14818,将相同变更带到维护线,同一发行版还修复了其他两个公告:wasi-http 内容长度冲突问题(GHSA-r8xh-cgf7-392j),以及 aarch64 br_table 跳转目标问题(CVE-2026-115893、GHSA-mghf-wjfp-p5xm)。

此修复完整覆盖该结构中的此类溢出:值不再经过任何缩窄步骤,因此函数无论多大都无法破坏映射。公告补充说,Cranelift 现在使用完整 u32 索引,并在超过该限制时进行检查,因此即使达到 u32 上限,也有保护,不会静默溢出。

如何检查是否已遭入侵?

该公告没有发布失陷指标。通过错误编译实现的沙箱逃逸没有公开特征或 IOC,也没有已知利用。如果您使用受影响引擎运行不可信客户模块,并希望审计:

  • 如果平台记录模块哈希或租户上传历史,请审查编译过哪些模块、由谁提供。针对该漏洞的特制模块会包含一个 SSA 值数量相对于字节大小异常高的函数。
  • 任何客户侧异常报告、表现为宿主崩溃的越界读取,或验证器按理应不允许的行为,都应成为调查宿主进程而非仅调查客户模块的依据。
  • 如果怀疑失陷,应将宿主进程视为完全失陷:轮换其持有的所有秘密,并从已知正常状态重新构建,因为逃逸的客户代码以宿主权限运行。

时间线

  • 2026 年 2 月 18 日:拉取请求 #12613“Cranelift:更新 ValueDataPacked 以支持完整 Value 范围”合并到主线。
  • 2026 年 3 月 20 日:Wasmtime 43.0.0 发布完整宽度编码。
  • 2026 年 10 月 14 日:Bytecode Alliance 发布 GHSA-m9f7-9w4p-gv38,即 macOS 和 FreeBSD 上通过带尾部斜杠的符号链接重命名触发的 wasmtime-wasi 文件系统沙箱逃逸,并发布包含修复的 36.0.18、48.0.6 和 49.0.3。
  • 2026 年 10 月 19 日:报告者 jaydns 获得致谢;Bytecode Alliance 发布公告 GHSA-897f-g5gm-fmxm 和伴随公告 GHSA-mghf-wjfp-p5xm(CVE-2026-115893,aarch64 br_table 逃逸),发布含两个回移修复的 36.0.19,以及含 br_table 修复的 48.0.7 和 49.0.4。
  • 2026 年 10 月 23 日:CVE-2026-115889 发布。
  • 2026 年 10 月 24 日:本文发布。三个漏洞均无已知在野利用;均未列入 CISA KEV 目录。
  • 2026 年 10 月 26 日:更新两个伴随公告 GHSA-mghf-wjfp-p5xm(CVE-2026-115893)和 GHSA-m9f7-9w4p-gv38。

常见问题

为什么主线在公告前几个月就得到了修复?

2 月将字段改为完整 u32 的变更取消了函数体大小限制。这是一项正确性改进,并非公开的安全修复。旧编码的安全影响后来才被报告,10 月公告记录了两个事实:v43 及更高版本不受影响,36.0.19 则为维护线回移此变更。

一个函数必须有 1670 万条指令才有风险吗?

不是。阈值针对打包进值记录的索引:指令、块和值索引,每类约 1670 万。值索引随 SSA 值数量增长,公告指出函数可以“专门构造以使用大量 SSA 值”。因此字节大小上限并不是可靠边界,应升级。

调试构建受影响吗?

不受影响。在调试构建中,debug_assert! 会触发,编译会中止,而不是破坏映射。生产引擎采用发布构建,这就是公告关注发布构建行为的原因。

Winch 后端或预编译模块路径受影响吗?

公告将漏洞范围限定为默认的 Cranelift 后端。运行预编译模块的引擎会跳过发生破坏的编译步骤,但仍应升级,因为公告没有排除其他后端或预编译路径。

Wasmtime 部署有多广泛?

在 crates.io 上,wasmtime crate 累计下载量为 41,373,089,过去 90 天下载量为 11,809,615。它也是限制第三方代码的无服务器和插件平台所使用的引擎,而这正是攻击者通过该漏洞跨越的边界。

设置了模块限制的 Wasmtime 平台也受影响吗?

如果内嵌引擎是受影响版本,就受影响。限制会缩小输入范围,但不是修复的一部分,因此应升级引擎,不要依赖上限。

升级至 43.0.0 或更高版本能消除全部三个漏洞吗?

不能。在主线上,CVE-2026-115889 自 43.0.0 起修复。文件系统逃逸最早在 48.0.6(49 线上为 49.0.3)修复,aarch64 br_table 逃逸最早在 48.0.7(49 线上为 49.0.4)修复。在 36.x 维护线上,36.0.19 消除全部三个漏洞。

参考资料

  • Bytecode Alliance 公告 GHSA-897f-g5gm-fmxm:https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-897f-g5gm-fmxm (核查于 2026 年 10 月 24 日)
  • Bytecode Alliance 公告 GHSA-mghf-wjfp-p5xm,CVE-2026-115893,aarch64 br_table 沙箱逃逸,严重,CVSS v3.1 9.9,修复版本为 36.0.19、48.0.7 和 49.0.4:https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-mghf-wjfp-p5xm (核查于 2026 年 10 月 26 日)
  • Bytecode Alliance 公告 GHSA-m9f7-9w4p-gv38,macOS 和 FreeBSD 上通过带尾部斜杠的符号链接重命名导致的 wasmtime-wasi 文件系统沙箱逃逸,高危,无 CVE,修复版本为 36.0.18、48.0.6 和 49.0.3:https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-m9f7-9w4p-gv38 (核查于 2026 年 10 月 26 日)
  • CVE-2026-115889 记录(CVSS v3.1 9.9、CWE-197 和 CWE-843、受影响范围):https://cveawg.mitre.org/api/cve/CVE-2026-115889 (核查于 2026 年 10 月 24 日)
  • 主线修复,拉取请求 #12613,2026 年 2 月 18 日合并:https://github.com/bytecodealliance/wasmtime/pull/12613 (核查于 2026 年 10 月 24 日)
  • Bytecode Alliance 公告 GHSA-r8xh-cgf7-392j,wasi-http 内容长度冲突,在同一 36.0.19 回移补丁中修复:https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-r8xh-cgf7-392j (核查于 2026 年 10 月 27 日)
  • 36.x 回移补丁,拉取请求 #14818:https://github.com/bytecodealliance/wasmtime/pull/14818 (核查于 2026 年 10 月 24 日)
  • Wasmtime 36.0.19 发行版(2026 年 10 月 19 日发布):https://github.com/bytecodealliance/wasmtime/releases/tag/v36.0.19 (核查于 2026 年 10 月 24 日)
  • Wasmtime 43.0.0 发行版(2026 年 3 月 20 日发布):https://github.com/bytecodealliance/wasmtime/releases/tag/v43.0.0 (核查于 2026 年 10 月 24 日)
  • 36.x 线中的易受攻击 dfg.rs(ValueDataPacked 编码):https://github.com/bytecodealliance/wasmtime/blob/v36.0.18/cranelift/codegen/src/ir/dfg.rs (核查于 2026 年 10 月 24 日)
  • crates.io 上 wasmtime 的下载量(累计 41,373,089,过去 90 天 11,809,615):https://crates.io/api/v1/crates/wasmtime (核查于 2026 年 10 月 24 日)