The vulnerability CVE-2026-92946 in vm2 arises from an insecure default configuration when NodeVM is initialized with require.external: true but without an explicit require.root. In this scenario, two default behaviors combine to defeat the sandbox: require.root defaults to unrestricted access, and require.context defaults to 'host', meaning modules are loaded and executed directly by the host's Node.js runtime.
The primary vulnerable component is the CustomResolver.isPathAllowed function within lib/resolver-compat.js. In the vulnerable version, this function contained logic that would unconditionally return true if this.rootPaths (which corresponds to the require.root option) was undefined. This effectively granted sandboxed code the ability to require() any arbitrary path on the host filesystem, bypassing intended security restrictions.
Once an arbitrary path is allowed by CustomResolver.isPathAllowed, the CustomResolver.loadJS function, also in lib/resolver-compat.js, becomes the execution vector. This function, under the default context: 'host', utilizes this.hostRequire(filename) to load the module. this.hostRequire is a reference to the real, unsandboxed Node.js require() function. Consequently, any module loaded through this path, including vm2's own internal modules (e.g., node_modules/vm2), would be executed in the host environment with full system privileges, leading to a complete sandbox escape and Remote Code Execution.
The provided patch addresses this by: (1) introducing a new isVm2SelfRequire check within CustomResolver.isPathAllowed to specifically deny sandboxed code from requiring vm2's own internal files, thereby preventing the nested NodeVM escape route; (2) adding a console.warn in makeResolverFromLegacyOptions to alert developers about the unsafe combination of require.external: true without require.root and a host context; and (3) modifying lib/cli.js to explicitly set root: pa.dirname(path) and context: 'sandbox' when running scripts, mitigating the vulnerability in the CLI's usage. The core vulnerability, however, lies in the permissive logic of CustomResolver.isPathAllowed and the subsequent unsandboxed execution via CustomResolver.loadJS in the absence of these critical checks.