vm2 NodeVM require.root Bypass via Symlink Traversal
A vulnerability exists in vm2 version 3.10.5 where NodeVM's `require.root` path restriction can be bypassed using filesystem symlinks, allowing sandboxed code to load modules from outside the allowed root directory in host context, leading to remote code execution.
The vm2 library, a popular Node.js sandbox, is vulnerable to a symlink bypass in version 3.10.5. This flaw allows sandboxed code to escape the intended restrictions imposed by the require.root option. The vulnerability arises because the path validation performed by isPathAllowed uses path.resolve(), which does not dereference symlinks. In contrast, Node.js’s native require() function, used for module loading, does follow symlinks. This discrepancy allows an attacker to create a symlink within the allowed root directory that points to a location outside the root, effectively bypassing the sandbox and enabling the loading of arbitrary host-realm modules. This can lead to remote code execution on the host system. The presence of symlinks is common in environments using pnpm, npm workspaces, or npm link.
Attack Chain
- Host application creates a
NodeVMinstance withrequire.rootset to a specific directory (e.g.,/tmp/root) andrequire.contextset tohost. - A symlink is created within the
require.rootdirectory (e.g.,/tmp/root/node_modules/safe) that points to a location outside the root directory (e.g.,/outside/root/vm2/). This symlink can be created using tools like pnpm or npm link. - Sandboxed code within the
NodeVMcallsrequire('safe'), intending to load a module from within the allowed root. - The
DefaultResolver.resolveFull()function resolves the module path to/tmp/root/node_modules/safe/index.js. - The
isPathAllowed()function checks if the resolved path starts with therequire.rootdirectory, which passes because the symlink is not yet resolved. - The
loadJS()function detects thatcontextis set tohostand callsthis.hostRequire(filename). - Node.js’s native
require()function follows the symlink, loading the module from the actual location outside the root directory,/outside/root/vm2/index.js. - The module from outside the intended sandbox is executed in the host realm, potentially granting the attacker the ability to execute arbitrary commands on the host system.
Impact
Successful exploitation allows untrusted sandboxed code to escape the vm2 sandbox, achieving remote code execution on the host system. An attacker can bypass the require.root restriction, a primary defense mechanism, and load arbitrary modules from the host realm. This is particularly impactful in environments that use pnpm, npm workspaces, or npm link, as these tools frequently create symlinks, making the vulnerability more readily exploitable. The vulnerability can lead to complete compromise of the host system.
Recommendation
- Apply the recommended remediation by dereferencing symlinks with
fs.realpathSyncbefore path validation inlib/filesystem.jsandlib/resolver-compat.jsas outlined in the advisory to prevent the bypass. - Deploy the “vm2 Sandbox Escape via Suspicious Host Require” Sigma rule to detect attempts to load modules from outside the intended sandbox via symlinks.
- Upgrade to a patched version of vm2 that includes the fix for CVE-2026-43998.
Detection coverage 2
vm2 Sandbox Escape via Suspicious Host Require
highDetects potential vm2 sandbox escapes by monitoring for require calls that load modules from outside the defined root path.
vm2 Sandbox Escape Attempt via Process Spawn
highDetects potential exploitation attempts by monitoring for process spawns initiated by vm2 with host context.
Detection queries are kept inside the platform. Get full rules →