事件概述
Node.js 沙箱库 vm2 在 2026 年 9 月 17 日集中披露了一批严重漏洞,影响 3.11.3 至 3.11.6 版本,全部在 3.11.7 中修复。vm2 常用于在服务端安全地运行不受信任的第三方 JavaScript 插件,一旦沙箱被突破,插件代码即可获得宿主进程权限。本批次中 CVE-2026-92940 的 CVSS 3.1 评分达到满分 10.0。
三个漏洞的技术路径
1. CVE-2026-92938:经由 node:sqlite 加载原生库
当 NodeVM 允许 node:sqlite 内置模块(显式允许或使用 builtin: ['*'])时,沙箱代码可以创建启用了扩展加载的内存数据库,并对插件包中自带的原生库调用 DatabaseSync.loadExtension()。SQLite 会把该库加载进 Node.js 宿主进程并调用其原生入口点,从而以宿主权限执行任意原生代码。另外,模块解析器只剥离一层 node: 前缀,因此写作 node:node:sqlite 的请求同样会被解析到真正的内置模块。CVSS 3.1 评分 9.9。
2. CVE-2026-92939:经由 crypto.setEngine 加载恶意引擎
同类问题的另一条路径是 crypto 模块。虽然它以递归只读代理的形式暴露给沙箱,但可调用的导出函数仍以宿主进程权限执行。沙箱代码由此可以调用 crypto.setEngine() 并传入一个指向攻击者可控原生库的文件路径,OpenSSL 会要求操作系统动态加载器载入该文件,其构造函数在引擎符号校验失败之前就已经在宿主进程中执行完毕。该路径不需要 fs、process、child_process、worker_threads 或 vm 等任何模块权限。CVSS 3.1 评分 9.9。
3. CVE-2026-92940:经由 https.globalAgent 窃取宿主凭据
当 NodeVM 显式允许 require('https') 时,宿主进程真实的 https.globalAgent 会被暴露。只读代理只拦截属性赋值,像 Agent.prototype.on() 这样的方法调用会被转发到底层宿主对象,沙箱代码因此可以监听 agent 的 free 事件。当宿主进程的某个无关 HTTPS 请求释放连接池中的连接时,监听者会收到该请求的实时 options 与宿主 TLSSocket,从而读取宿主的 Authorization 头与目标主机端口、附着数据监听器明文读取后续响应,并用窃取到的凭据发起认证请求。CVSS 3.1 与 CVSS 4.0 均为 10.0。
影响评估与修复建议
- 受影响版本:vm2 3.11.3 至 3.11.6;修复版本:3.11.7
- 目前未见公开的在野利用信号,也未见公开的利用代码,但漏洞目标价值高
- 三类问题共同指向同一个设计缺陷:只读代理能阻止赋值,却无法阻止方法调用与可调用导出被转发到宿主对象
处置上,任何把 vm2 用作安全边界的场景都应立即升级到 3.11.7 及以上。如果暂时无法升级,应优先收紧 NodeVM 的内置模块白名单,至少移除 crypto、node:sqlite、https,避免使用 builtin: ['*']。需要强调的是,把 vm2 当作通用隔离子系统本身已多次被证明不可靠,涉及不受信任代码执行的场景建议评估进程级或容器级隔离。