CVE-2026-92941: Vm2 Vm2 NodeVM Can Replace The Vulnerability

CRITICAL
Advisory Identifier: GHSA-98xx-8mx4-x7cm
CVSS 10.0
CWE-732
Published
Advisory Summary

CVE-2026-92941 is a CRITICAL (CVSS 10.0) vm2 nodevm can replace the vulnerability (CWE-732: Incorrect Permission Assignment for Critical Resource) affecting Vm2 libraries in the npm ecosystem. The issue involves vm2 nodevm can replace the host process tls trust store. Remediation is available by upgrading affected packages to version 3.11.7.

CVE-2026-92941 at a Glance

CVE Identifier CVE-2026-92941
GHSA Identifier GHSA-98xx-8mx4-x7cm
Severity CRITICAL
CVSS v3.1 Base Score 10.0
CWE Classification CWE-732: Incorrect Permission Assignment for Critical Resource
Affected Product Vm2
Package Ecosystem npm
Published Date
Last Updated

Security Impact

CVSS: 10.0

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Changed (S:C)
Confidentiality High (C:H)
Integrity High (I:H)
Availability Low (A:L)

How to Fix CVE-2026-92941

To remediate this vulnerability, upgrade all affected Vm2 dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

vm2 fixed: 3.11.7
npm install vm2@3.11.7
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls vm2

How to Check if You Are Affected

To determine whether your Node.js application is affected by CVE-2026-92941, inspect your project dependencies using npm:

npm ls vm2

Analyze the terminal output to locate any version of Vm2 in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 3.11.7), your application is affected.

Note: The npm ls vm2 command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-732: Incorrect Permission Assignment for Critical Resource, where the product specifies permissions for a security-critical resource in a way that allows that resource to be read or modified by unintended actors. In Vm2, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

Summary vm2 3.11.6 exposes the host `tls` module to a `NodeVM` when that builtin is explicitly allowed. Although the module object is wrapped as read-only, its functions still execute against process-wide host state. On Node.js versions that provide `tls.setDefaultCACertificates()`, sandbox code can replace the certificate authorities trusted by subsequent host-realm TLS clients. The exploit needs only the narrowly allowed `tls` and `url` builtins. It does not require `fs`, `process`, `module`, `child_process`, an external package, or a general `'*'` builtin grant. A host HTTPS request rejected an attacker certificate before sandbox execution, then accepted the same certificate and returned an application marker after the sandbox replaced the default CA list. This crosses the intended sandbox boundary. An attacker can make host HTTPS clients trust an attacker-controlled CA, enabling credential theft and response tampering when the attacker can influence a subsequent destination or network path. Replacing the list also removes the normal trust roots, disrupting unrelated host TLS traffic. ### Details The vulnerable boundary is the default builtin loader in `lib/builtin.js`. Builtins that are not classified as dangerous are exposed through a recursive read-only bridge: ```js builtins.set(key, special ? special : vm => vm.readonly(hostRequire(key))); ``` The read-only wrapper prevents ordinary property assignment through the sandbox proxy. It does not make calls such as `tls.setDefaultCACertificates()` sandbox-local. That function changes the default CA list for the current Node.js thread and affects subsequent TLS connections that do not provide their own `ca` option. The dangerous-builtin list now rejects `dns` because `dns.setServers()` mutates process-wide host networking state. It does not reject `tls`, even though current Node.js exposes an equivalent process-wide trust mutation through it. A direct call with a normal sandbox array is not necessary. The native TLS function requires an actual host-realm array. The allowed host `url` module provides one: ```js const tls = require('tls'); const {URLSearchParams} = require('url'); const hostArray = new URLSearchParams( 'ca=' + encodeURIComponent(attackerCaPem) ).getAll('ca'); tls.setDefaultCACertificates(hostArray); ``` `URLSearchParams.getAll()` executes in the host realm and returns a host array containing the attacker-controlled PEM string. vm2 maps that array into the sandbox. When the mapped value is passed back to the TLS function, the bridge unwraps it to the original host array, satisfying the native type check. The TLS function then replaces the host thread's default CA set. The complete exploit flow is: ```text attacker-controlled NodeVM program -> require only the allowed tls and url builtins -> URLSearchParams.getAll() creates a host array containing attacker CA PEM -> bridge unwraps the mapped array when passed back to tls -> tls.setDefaultCACertificates() replaces host default trust roots -> subsequent host-realm HTTPS client accepts attacker-signed certificates -> attacker can observe or modify application TLS traffic ``` The API is present in Node.js 22.19.0 and later in the 22.x line, and Node.js 24.5.0 and later in the 24.x line. ### PoC The attached PoC is fully local. It creates a temporary CA and a loopback HTTPS server signed by that CA, then performs two requests from the host realm. 1. Install Node.js 22.19.0 or later in the 22.x line, or Node.js 24.5.0 or later in the 24.x line. OpenSSL must also be available. 2. In the attached `poc` directory, run: ```bash npm install --ignore-scripts node poc.js ``` 3. A vulnerable result has all of these properties: - the first host request fails with a certificate verification error; - the sandbox reports that it supplied one host-realm CA entry; - the second host request succeeds with HTTP 200; - the second response body is `VM2_POC_HOST_TLS_RESPONSE_3e71c8`. The server listens only on loopback and the PoC makes no external request. ### Impact This is an improper sandbox authorization boundary around a process-wide TLS security setting. An attacker who can submit code to a `NodeVM` configured with the `tls` and `url` builtins can: - replace the CAs used by subsequent host-side HTTPS and TLS clients; - make the host authenticate services presenting certificates signed by the attacker; - intercept host credentials, API tokens, session data, request bodies, and responses when the attacker can influence DNS, routing, a proxy, or a later request destination; - modify trusted responses, including configuration, webhook, update, identity, and package-retrieval traffic; - remove the normal trusted roots and cause unrelated host TLS connections to fail. The attacker does not obtain a direct file or command-execution primitive from this PoC. The critical impact is control of the host process's authentication trust decision, outside the sandbox's authority. Connections that explicitly provide their own CA list are not affected, and already cached TLS sessions may remain unchanged.

CVE-2026-92941 Affected Vm2 Versions

1 component(s)
Fixed Versions:
3.11.7
Product / Package Ecosystem Affected Versions Fixed Version
vm2
npm
≥ 3.11.3
< 3.11.7
3.11.7

References

Frequently Asked Questions

What is CVE-2026-92941?
CVE-2026-92941 is a security vulnerability in Vm2 involving vm2 NodeVM can replace the host process TLS trust store under CWE-732: Incorrect Permission Assignment for Critical Resource.
Which Vm2 versions are affected?
Affected versions include releases prior to 3.11.7 across affected packages: vm2.
What version fixes CVE-2026-92941?
Upgrading to 3.11.7 (or the latest patched release for your respective branch) resolves the vulnerability.
Is vm2 affected?
Yes, vm2 is affected in releases prior to 3.11.7. Upgrade your dependency to 3.11.7 or later.
What is the CVSS score of CVE-2026-92941?
CVE-2026-92941 has a CVSS v3.1 base score of 10.0 (CRITICAL) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L.
What CWE is associated with CVE-2026-92941?
CVE-2026-92941 is classified under CWE-732: Incorrect Permission Assignment for Critical Resource (The product specifies permissions for a security-critical resource in a way that allows that resource to be read or modified by unintended actors.).
How can I check npm dependencies for CVE-2026-92941?
Run the dependency tree command: 'npm ls vm2'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-98xx-8mx4-x7cm",
  "modified" : "2026-10-01T15:27:28Z",
  "published" : "2026-10-01T15:27:28Z",
  "aliases" : [ "CVE-2026-92941" ],
  "summary" : "vm2 NodeVM can replace the host process TLS trust store",
  "details" : "Summary\n\nvm2 3.11.6 exposes the host `tls` module to a `NodeVM` when that builtin is explicitly allowed. Although the module object is wrapped as read-only, its functions still execute against process-wide host state. On Node.js versions that provide `tls.setDefaultCACertificates()`, sandbox code can replace the certificate authorities trusted by subsequent host-realm TLS clients.\n\nThe exploit needs only the narrowly allowed `tls` and `url` builtins. It does not require `fs`, `process`, `module`, `child_process`, an external package, or a general `'*'` builtin grant. A host HTTPS request rejected an attacker certificate before sandbox execution, then accepted the same certificate and returned an application marker after the sandbox replaced the default CA list.\n\nThis crosses the intended sandbox boundary. An attacker can make host HTTPS clients trust an attacker-controlled CA, enabling credential theft and response tampering when the attacker can influence a subsequent destination or network path. Replacing the list also removes the normal trust roots, disrupting unrelated host TLS traffic.\n\n### Details\n\nThe vulnerable boundary is the default builtin loader in `lib/builtin.js`. Builtins that are not classified as dangerous are exposed through a recursive read-only bridge:\n\n```js\nbuiltins.set(key, special ? special : vm => vm.readonly(hostRequire(key)));\n```\n\nThe read-only wrapper prevents ordinary property assignment through the sandbox proxy. It does not make calls such as `tls.setDefaultCACertificates()` sandbox-local. That function changes the default CA list for the current Node.js thread and affects subsequent TLS connections that do not provide their own `ca` option.\n\nThe dangerous-builtin list now rejects `dns` because `dns.setServers()` mutates process-wide host networking state. It does not reject `tls`, even though current Node.js exposes an equivalent process-wide trust mutation through it.\n\nA direct call with a normal sandbox array is not necessary. The native TLS function requires an actual host-realm array. The allowed host `url` module provides one:\n\n```js\nconst tls = require('tls');\nconst {URLSearchParams} = require('url');\n\nconst hostArray = new URLSearchParams(\n  'ca=' + encodeURIComponent(attackerCaPem)\n).getAll('ca');\n\ntls.setDefaultCACertificates(hostArray);\n```\n\n`URLSearchParams.getAll()` executes in the host realm and returns a host array containing the attacker-controlled PEM string. vm2 maps that array into the sandbox. When the mapped value is passed back to the TLS function, the bridge unwraps it to the original host array, satisfying the native type check. The TLS function then replaces the host thread's default CA set.\n\nThe complete exploit flow is:\n\n```text\nattacker-controlled NodeVM program\n  -> require only the allowed tls and url builtins\n  -> URLSearchParams.getAll() creates a host array containing attacker CA PEM\n  -> bridge unwraps the mapped array when passed back to tls\n  -> tls.setDefaultCACertificates() replaces host default trust roots\n  -> subsequent host-realm HTTPS client accepts attacker-signed certificates\n  -> attacker can observe or modify application TLS traffic\n```\n\nThe API is present in Node.js 22.19.0 and later in the 22.x line, and Node.js 24.5.0 and later in the 24.x line.\n\n### PoC\n\nThe attached PoC is fully local. It creates a temporary CA and a loopback HTTPS server signed by that CA, then performs two requests from the host realm.\n\n1. Install Node.js 22.19.0 or later in the 22.x line, or Node.js 24.5.0 or later in the 24.x line. OpenSSL must also be available.\n2. In the attached `poc` directory, run:\n\n   ```bash\n   npm install --ignore-scripts\n   node poc.js\n   ```\n\n3. A vulnerable result has all of these properties:\n\n   - the first host request fails with a certificate verification error;\n   - the sandbox reports that it supplied one host-realm CA entry;\n   - the second host request succeeds with HTTP 200;\n   - the second response body is `VM2_POC_HOST_TLS_RESPONSE_3e71c8`.\n\nThe server listens only on loopback and the PoC makes no external request.\n\n### Impact\n\nThis is an improper sandbox authorization boundary around a process-wide TLS security setting.\n\nAn attacker who can submit code to a `NodeVM` configured with the `tls` and `url` builtins can:\n\n- replace the CAs used by subsequent host-side HTTPS and TLS clients;\n- make the host authenticate services presenting certificates signed by the attacker;\n- intercept host credentials, API tokens, session data, request bodies, and responses when the attacker can influence DNS, routing, a proxy, or a later request destination;\n- modify trusted responses, including configuration, webhook, update, identity, and package-retrieval traffic;\n- remove the normal trusted roots and cause unrelated host TLS connections to fail.\n\nThe attacker does not obtain a direct file or command-execution primitive from this PoC. The critical impact is control of the host process's authentication trust decision, outside the sandbox's authority. Connections that explicitly provide their own CA list are not affected, and already cached TLS sessions may remain unchanged.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "vm2"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "3.11.3"
      }, {
        "fixed" : "3.11.7"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 3.11.6"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/patriksimek/vm2/security/advisories/GHSA-98xx-8mx4-x7cm"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-92941"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/patriksimek/vm2/commit/aa146a77f859325e079f3bfbfe6d8309af483daa"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/patriksimek/vm2"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/patriksimek/vm2/releases/tag/v3.11.7"
  }, {
    "type" : "WEB",
    "url" : "https://www.vulncheck.com/advisories/vm2-3.11.3-before-3.11.7-tls-trust-store-manipulation"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-732" ],
    "severity" : "CRITICAL",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-10-01T15:27:28Z",
    "nvd_published_at" : null
  }
}