CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-92952

CVE-2026-92952: Sandbox Escape and State Corruption in vm2 via Node.js-internal Symbol Leak

Amit Schendel
Amit Schendel
Senior Security Researcher

Oct 1, 2026·6 min read·5 visits

Executive Summary (TL;DR)

An incomplete blocklist of Node.js-internal symbols in vm2 (3.11.4-3.11.6) allows sandboxed code to access host-realm stream symbols, corrupt stream state accessors on the host, and bypass security gates.

A high-severity sandbox escape and state corruption vulnerability exists in the vm2 library (versions 3.11.4 through 3.11.6). The vulnerability is caused by an incomplete blocklist of Node.js-internal registered symbols crossing the sandbox-host bridge boundary. Specifically, the filters in `lib/setup-sandbox.js` and write traps in `lib/bridge.js` omitted the symbols `nodejs.stream.disturbed` and `nodejs.stream.errored`, allowing untrusted code within the sandbox to corrupt host-realm stream state checks.

Vulnerability Overview

The vm2 library is designed to run untrusted JavaScript code in a sandboxed V8 isolate environment within a Node.js process. To facilitate communication between the restricted sandbox and the host environment, vm2 establishes a bridge governed by JavaScript Proxies. These proxies intercept operations like property access, object definition, and function execution to ensure sandbox isolation.

An essential requirement of this architecture is the complete isolation of internal metadata from crossing the boundary. Node.js uses specific globally registered Symbol objects, such as those prefixed with nodejs., to designate internal object states across realms. If a sandboxed script can access these internal symbols, it can leverage proxy write traps to override or inject properties directly onto live objects in the host environment.

In modern Node.js runtimes (Node.js 18+), internal state indicators for Web Streams are stored on ReadableStream.prototype utilizing symbols. Due to omission in the symbol sanitization lists of vm2 versions 3.11.4 through 3.11.6, untrusted sandboxed code can extract host-realm symbols and manipulate the internal state checks of host-visible stream instances.

Root Cause Analysis

The root cause of this vulnerability lies in the missing sanitization of the global symbols Symbol.for('nodejs.stream.disturbed') and Symbol.for('nodejs.stream.errored') within the vm2 bridge. These specific symbols are used by Node.js internally to keep track of whether a web stream has been read, cancelled, or has entered an error state.

When standard stream operations are evaluated, the Node.js helper function stream.Readable.isDisturbed() evaluates whether a stream's content has already been consumed. It achieves this by reading the internal state accessor matching the symbol nodejs.stream.disturbed. If this property evaluates to a truthy value, the helper confirms the stream is consumed, preventing subsequent reads and enforcing single-consumption rules.

Because the vm2 proxy bridge failed to include these symbols in its static filtering list, sandboxed code could enumerate the symbols present on ReadableStream.prototype. After extracting the real symbol, the sandbox can issue a write command via Object.defineProperty on a host-realm stream instance. This defines an "own" property on the host stream instance with the value false, shadowing the prototype getter. When the host environment subsequently calls isDisturbed(), the nullish coalescing operator short-circuits on the shadowed false value, leading the host to believe the stream is unconsumed.

Code Analysis and Diff Breakdown

The vulnerability was resolved in version 3.11.7 via commit a45444d5abbdfa59055528f584df5f21cc7c42da. Instead of continuously updating a static list of dangerous symbols, the maintainers implemented a generalized namespace-based catch-all verification mechanism.

At bootstrap time, pristine references to runtime operations are cached before any untrusted sandbox code execution can compromise them. Specifically, Symbol.keyFor and String.prototype.startsWith are secured:

// In lib/bridge.js
const thisSymbolKeyFor = Symbol.keyFor;
const thisStringPrototypeStartsWith = String.prototype.startsWith;

The check function isDangerousCrossRealmSymbol was modified to intercept all registered symbols that reside within the reserved nodejs. namespace. This namespace-based approach closes the recurring maintenance gap that previously required updating explicit lists for individual Node.js versions:

function isDangerousCrossRealmSymbol(key) {
	if (typeof key !== 'symbol') return false;
 
	// Resolve the global registration key for the symbol
	const nsKey = thisSymbolKeyFor(key);
	
	// If the symbol is registered and starts with 'nodejs.', block it
	if (typeof nsKey === 'string' && thisReflectApply(thisStringPrototypeStartsWith, nsKey, ['nodejs.'])) return true;
	
	return (
		key === thisSymbolNodeJSUtilInspectCustom ||
		key === thisSymbolNodeJSRejection ||
		// ... traditional fallback checks
	);
}

A similar change was mirrored within lib/setup-sandbox.js inside the isDangerousSymbol function to ensure that extraction techniques utilizing getOwnPropertySymbols or Reflect.ownKeys are stripped of any nodejs. namespace symbols before surfacing back to the sandboxed runtime.

Exploitation and Attack Vector

To execute this sandbox escape, the sandboxed environment must have access to a host-exposed stream prototype or an instance of a web stream. The attack consists of three distinct phases: symbol extraction, target instantiation, and property shadowing.

First, the attacker inspects the prototype of a web stream, extracting its symbol array:

const streamProto = ReadableStream.prototype;
const targetSymbol = Object.getOwnPropertySymbols(streamProto)
  .find(sym => sym.description === 'nodejs.stream.disturbed');

Second, the sandboxed attacker target-defines this symbol on an active, fully consumed stream exposed from the host realm. By setting the descriptor value to false, the attacker intercepts the prototype getter:

Object.defineProperty(hostStream, targetSymbol, {
  value: false,
  configurable: true
});

When the hosting environment processes the stream, checks like stream.Readable.isDisturbed(hostStream) evaluate the shadowed value and erroneously return false. This allows the sandboxed application to manipulate state-dependent application logic, bypass integrity constraints, and force the host program to reuse read-once stream bodies.

Impact Assessment

The CVSS v4.0 rating assigns this vulnerability a base score of 8.9 (High Severity), reflecting the significant integrity impact on hosting systems. The vulnerability violates core sandbox isolation boundaries, allowing low-privilege script execution layers to corrupt state validation processes of high-privilege host runtimes.

Depending on how the hosting application integrates streams, this behavior has different concrete outcomes. If the application processes sensitive transactions, payload body validations, or authentication messages using streams, the integrity check bypass can allow an attacker to replay inputs, process malformed or previously closed data channels, or induce logic errors in the host's middleware handlers.

Due to the structural difficulty in defending V8-level proxy bridges from recurring symbol and prototype leaks, the overall integrity of the vm2 sandbox boundary is compromised, making it unsuitable for processing fully untrusted code.

Mitigation & Remediation

The primary remediation strategy is upgrading the library to version 3.11.7 or higher. This release integrates the namespace-based symbol checks that block all registered symbols prefixed with nodejs. from crossing the proxy bridge.

However, because the vm2 library is deprecated and the maintainers have officially archived the project, the recommended long-term remediation strategy is to migrate away from vm2 entirely. Applications executing untrusted scripts must transition to process-isolated architectures, such as executing scripts in separate short-lived subprocesses confined by system-level permissions (e.g., Docker, seccomp, gVisor), or utilizing V8 isolates through libraries designed with out-of-process boundaries like isolated-vm.

Official Patches

patriksimekCommit implementing namespace-based symbol filtering.

Fix Analysis (1)

Technical Appendix

CVSS Score
8.9/ 10
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:H/SA:N
EPSS Probability
0.46%
Top 62% most exploited

Affected Systems

vm2 library (versions 3.11.4 through 3.11.6) running on Node.js runtimes containing web streams

Affected Versions Detail

Product
Affected Versions
Fixed Version
vm2
patriksimek
>= 3.11.4, <= 3.11.63.11.7
AttributeDetail
CWE IDCWE-669
Attack VectorAdjacent/Remote dependent on application exposure
CVSS v4.0 Score8.9
EPSS Score0.00461 (Percentile: 37.62%)
ImpactHigh Integrity Impact / Sandbox Escape
Exploit StatusPoC / Non-weaponized
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1562Impair Defenses
Defense Evasion
T1055Process Injection
Privilege Escalation
CWE-669
Incorrect Resource Transfer Between Spheres

The product does not properly prevent resources from crossing an architectural boundary, such as a sandbox.

Known Exploits & Detection

GitHubThe advisory contains structural details and unit test definitions showing how the bypass behaves on modern Node.js versions.

References & Sources

  • [1]NVD Record for CVE-2026-92952
  • [2]GitHub Security Advisory GHSA-jf8q-945g-9q4c
  • [3]vm2 v3.11.7 Release Notes
  • [4]VulnCheck Advisory Portal

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•1 minute ago•CVE-2026-92950
9.3

CVE-2026-92950: Sandbox Escape Vulnerability in vm2 CLI

CVE-2026-92950 (GHSA-jxxv-8r27-vm4p) is a critical sandbox escape vulnerability in the command-line interface of the vm2 library prior to version 3.11.7. The flaw allows untrusted scripts to bypass sandbox constraints and execute arbitrary system commands with the privileges of the host process by exploiting insecure default configurations of the module resolver.

Amit Schendel
Amit Schendel
0 views•5 min read
•about 1 hour ago•CVE-2026-92948
9.9

CVE-2026-92948: Sandbox Escape and Remote Code Execution in vm2 via node:test

CVE-2026-92948 is a critical sandbox escape vulnerability in the vm2 library affecting versions 3.9.6 through 3.11.6 when executed on Node.js 24 and newer. The vulnerability allows an attacker to bypass built-in module blocking defenses by double-prefixing a restricted module name (such as node:node:test). This permits the loading of the node:test module, whose test runner execution can be leveraged to execute arbitrary shell commands outside the VM sandbox.

Amit Schendel
Amit Schendel
3 views•6 min read
•about 3 hours ago•CVE-2026-73607
5.8

CVE-2026-73607: Missing Authorization in SiYuan /api/storage/getOutlineStorage Leads to Information Disclosure

An architectural evaluation of CVE-2026-73607 in the SiYuan personal knowledge management system. This technical advisory details a Missing Authorization (CWE-862) vulnerability in the Go-based backend kernel, specifically within the outline storage API endpoint. Under certain configurations, authenticated low-privilege users can query metadata, heading structures, and block hierarchies of restricted documents.

Amit Schendel
Amit Schendel
5 views•7 min read
•about 4 hours ago•CVE-2026-73609
5.8

CVE-2026-73609: Missing Authorization in SiYuan Note getBookmarkLabels Endpoint

An information disclosure vulnerability (CWE-862) in the SiYuan Note platform before version v3.7.4 allows anonymous or unprivileged readers to obtain a complete list of bookmark labels globally across all workspaces and notebooks by querying the `/api/attr/getBookmarkLabels` API endpoint.

Alon Barad
Alon Barad
6 views•6 min read
•about 6 hours ago•GHSA-9CQF-HHRQ-7V45
5.3

Missing publish-access check on getAttributeViewSearchTarget endpoint exposes database row content to unauthorized readers

An authorization bypass and information leakage vulnerability exists in the SiYuan database module. Unauthenticated users can query the getAttributeViewSearchTarget API endpoint using target block identifiers to extract private content.

Alon Barad
Alon Barad
6 views•5 min read
•about 7 hours ago•CVE-2026-76504
9.8

CVE-2026-76504: Unauthenticated Authentication Bypass in Cisco Catalyst SD-WAN Manager

CVE-2026-76504 is a critical vulnerability in the web-based management console of Cisco Catalyst SD-WAN Manager. Due to improper normalization and handling of hex/percent-encoded sequences (CWE-177) within incoming request URIs, remote, unauthenticated attackers can bypass administrative authentication controls. Successful exploitation permits full remote administrative command execution on the SD-WAN management plane, threatening the integrity and availability of the managed network fabric.

Amit Schendel
Amit Schendel
13 views•7 min read