CVE-2026-92938 in vm2
Summary
by MITRE • 09/17/2026
vm2 versions 3.11.3 through 3.11.6 expose Node.js's host node:sqlite module to code running in NodeVM when that builtin is permitted, either explicitly or through builtin: ['*']. The module is wrapped with vm.readonly(), which prevents property assignment but leaves host-authority callables reachable; in addition, the resolver treats any request starting with 'node:' as a core-module request and the runtime strips only one 'node:' prefix, so a sandbox request for 'node:node:sqlite' resolves to the configured node:sqlite entry. Sandboxed code can therefore create an in-memory DatabaseSync with extension loading enabled and call DatabaseSync.loadExtension() on a native library bundled in the untrusted plugin package (path derived from __dirname). SQLite loads the library into the Node.js host process and invokes its native entry point, giving the sandboxed plugin arbitrary native code execution outside the sandbox with the host process's privileges. The issue is fixed in vm2 3.11.7.
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.
Analysis
by VulDB Data Team • 09/17/2026
The vulnerability identified in versions of the vm2 library between 3.11.3 and 3.11.6 represents a critical failure in sandbox isolation, specifically concerning the handling of Node.js core modules that provide access to native system resources. The root cause lies in how the library resolves module paths when the node:sqlite builtin is permitted within the virtual machine configuration. While vm2 attempts to mitigate risks by wrapping host-authority callables with a readonly mechanism intended to prevent property assignment, this protection proves insufficient against sophisticated exploitation techniques that leverage path resolution quirks and native extension loading capabilities inherent to SQLite.
The technical flaw stems from two distinct but compounding issues within the module resolver logic. First, the resolver treats any request string starting with node: as a core-module request without sufficiently validating the subsequent path components for safety or sandbox restrictions. Second, the runtime implementation strips only one instance of the node: prefix during resolution. This behavior allows an attacker to craft a maliciously constructed module identifier such as node:node:sqlite. When this identifier is processed by the vulnerable resolver, it results in the successful loading and exposure of the actual node:sqlite host module rather than failing or remaining sandboxed. Consequently, code executing within the VM gains access to powerful database operations that interact directly with the underlying operating system through native bindings.
Once access to the node:sqlite module is established, an attacker can instantiate a DatabaseSync object with extension loading explicitly enabled. This configuration allows the execution of SQLite extensions written in C or other compiled languages. By invoking the loadExtension method and providing a path derived from __dirname within the sandboxed environment, the malicious code directs SQLite to load a native library bundled alongside untrusted plugin packages. The critical consequence is that this action causes SQLite to inject and execute arbitrary native machine code directly into the Node.js host process memory space. This effectively bypasses all JavaScript-level security controls and sandbox boundaries, granting the attacker full control over the host environment with the same privileges as the running Node.js application.
From a threat modeling perspective, this vulnerability aligns closely with CWE-94 Improper Control of Generation of Code (Code Injection) and CWE-78 Improper Neutralization of Special Elements used in an OS Command (OS Command Injection), although it specifically targets native code execution rather than shell commands. In the context of the MITRE ATT&CK framework, this exploit maps to T1059 Command and Scripting Interpreter via JavaScript, but more critically to T1203 Exploitation for Client Execution or potentially T1610 Deploy Capability if viewed as establishing a foothold within the host process. The ability to execute arbitrary native code outside the sandbox constitutes a complete breakdown of isolation guarantees, allowing for data exfiltration, privilege escalation, and further lateral movement depending on the context in which the Node.js application operates.
The operational impact is severe, particularly for applications that utilize vm2 to run untrusted user-supplied plugins or scripts. If such an application processes maliciously crafted input designed to trigger this module resolution flaw, it can lead to remote code execution with host-level privileges. This compromises not only the confidentiality and integrity of data processed by the application but also potentially exposes other services running on the same infrastructure if they share access credentials or network segments accessible from the compromised host process. The lack of proper validation for nested node: prefixes in module requests highlights a significant oversight in security-by-design principles when integrating complex native modules into sandboxed environments.
To mitigate this risk, organizations must immediately upgrade to vm2 version 3.11.7 or later, where these path resolution and extension loading vulnerabilities have been addressed. For systems that cannot be updated instantly, it is imperative to restrict the builtins available within VM instances strictly to those absolutely necessary for functionality, avoiding wildcard configurations like builtin: ['*'] whenever possible. Additionally, implementing strict allowlists for module names can prevent the resolution of unexpected core modules. Security teams should also audit existing codebases for any usage of node:sqlite or similar native database libraries within sandboxed contexts and evaluate whether alternative approaches that do not rely on vm2's isolation guarantees are viable for handling untrusted input.