Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-47141

CVE-2026-47141: vm2 Information Disclosure Vulnerability

CVE-2026-47141 is an information disclosure flaw in vm2 that allows sandboxed code to observe host application data across the sandbox boundary. This post covers technical details, affected versions, and mitigation.

Published:

CVE-2026-47141 Overview

CVE-2026-47141 affects vm2, an open source virtual machine and sandbox library for Node.js. Versions prior to 3.11.4 allow sandboxed code to access process-wide observability builtins through require.builtin. The diagnostics_channel, async_hooks, and perf_hooks modules are not blocked by the dangerous builtin denylist. These modules expose state from the entire host process rather than the sandbox, allowing sandboxed code to observe host application data across the vm2 boundary. The maintainers patched the issue in version 3.11.4. This weakness is categorized as exposure of resource to wrong sphere [CWE-668].

Critical Impact

Sandboxed code can read host-side HTTP request data, authentication context, and performance marks, breaking the isolation guarantees of NodeVM.

Affected Products

  • vm2 versions prior to 3.11.4
  • Node.js applications embedding NodeVM with require.builtin enabled
  • Downstream packages depending on vulnerable vm2 releases

Discovery Timeline

  • 2026-06-12 - CVE-2026-47141 published to the National Vulnerability Database
  • 2026-06-17 - Last updated in NVD database

Technical Details for CVE-2026-47141

Vulnerability Analysis

The vm2 library implements a sandbox that exposes a configurable list of allowed Node.js builtins to guest code through require.builtin. The library maintains a denylist intended to block builtins that can break out of or peek through the sandbox boundary. The denylist did not cover diagnostics_channel, async_hooks, and perf_hooks. These modules report on activity inside the host Node.js process itself, not just the sandbox context. Guest code obtaining a reference to any of these modules can subscribe to host activity in real time.

For example, calling dc.channel('http.server.request.start').subscribe(cb) delivers raw IncomingMessage objects from every request the embedding application receives, including Authorization and session cookie headers. The async_hooks module exposes executionAsyncResource(), which returns the host's current AsyncResource and any AsyncLocalStorage state pinned to it. The perf_hooks module surfaces every performance.mark() call made by the host, often containing request IDs, user IDs, or query strings.

Root Cause

The root cause is an incomplete denylist in lib/builtin.js. The vm2 boundary cannot contain modules whose data describes the embedder process. Even a read-only proxy that forwards calls to the underlying host module still functions as an exfiltration primitive.

Attack Vector

An attacker who can execute JavaScript inside a NodeVM instance requires any builtin permission that includes the missing modules. The attacker calls require('diagnostics_channel'), require('async_hooks'), or require('perf_hooks') and subscribes to host events. No additional privileges or user interaction are needed.

javascript
// Security patch in lib/builtin.js - fix(GHSA-9g8x-92q2-p28f)
// Source: https://github.com/patriksimek/vm2/commit/e1c48fce05189f48e71efbd32af0754efa4066bb

	// `preopens: {}` exposes the host CWD when sandbox code constructs
	// a WASI module. Embedders who genuinely need WASI can register a
	// controlled wrapper via `mock`/`override`.
-	'wasi'
+	'wasi',
+	// SECURITY (GHSA-9g8x-92q2-p28f): Process-wide observability builtins.
+	// Unlike most Node builtins, these expose state of the *entire host
+	// process* rather than sandbox-local state -- the vm2 boundary cannot
+	// usefully contain them because the data they surface (HTTP requests,
+	// async-context, perf marks, heap contents) belongs to the embedder.
+	//   - diagnostics_channel : `dc.channel('http.server.request.start').subscribe(cb)`
+	//                           hands the sandbox raw host IncomingMessage
+	//                           objects -- including Authorization /
+	//                           session-token headers.
+	//   - async_hooks         : `executionAsyncResource()` returns the host's
+	//                           current AsyncResource pinned via AsyncLocalStorage.
+	//   - perf_hooks          : `performance.getEntriesByType('mark')` reads
+	//                           every host-side `performance.mark(name)`.
+	//   - v8                  : `v8.getHeapSnapshot()` serializes the entire
+	//                           host V8 heap.

The patch adds diagnostics_channel, async_hooks, perf_hooks, and v8 to the denylist enforced by NodeVM. See the vm2 GitHub Security Advisory GHSA-9g8x-92q2-p28f for the full disclosure.

Detection Methods for CVE-2026-47141

Indicators of Compromise

  • Sandboxed scripts invoking require('diagnostics_channel'), require('async_hooks'), or require('perf_hooks')
  • Unexpected subscribers registered on http.server.request.start or other diagnostics channels in production processes
  • Outbound network connections from Node.js services that correlate with inbound HTTP requests carrying authorization headers

Detection Strategies

  • Inventory all applications embedding vm2 and identify versions below 3.11.4 using software composition analysis
  • Audit NodeVM configurations for require.builtin settings that permit observability modules
  • Instrument the host process to log calls to diagnostics_channel.subscribe and executionAsyncResource() originating from sandbox contexts

Monitoring Recommendations

  • Forward Node.js application logs to a centralized analytics platform and alert on sandbox require() calls that reference observability builtins
  • Track dependency manifests in source control and trigger alerts on installations of vm2 versions less than 3.11.4
  • Correlate process telemetry with inbound HTTP traffic to detect unusual cross-context data flow

How to Mitigate CVE-2026-47141

Immediate Actions Required

  • Upgrade vm2 to version 3.11.4 or later in all affected applications
  • Review every NodeVM instance and remove diagnostics_channel, async_hooks, perf_hooks, and v8 from any custom allowlist
  • Rotate credentials and session tokens that may have been observable through the affected channels

Patch Information

The fix is available in vm2 release v3.11.4. The commit e1c48fce05189f48e71efbd32af0754efa4066bb adds the process-wide observability modules to the denylist in lib/builtin.js. Refer to the upstream patch commit for implementation detail.

Workarounds

  • Migrate away from vm2, which is no longer recommended for untrusted code execution, toward isolated-process or VM-based sandboxes
  • Explicitly restrict require.builtin to a minimal allowlist that excludes observability modules until upgrade is possible
  • Run sandboxed workloads in dedicated Node.js processes with no access to host secrets or request data
bash
# Configuration example: upgrade vm2 and pin the fixed version
npm install vm2@^3.11.4
npm ls vm2

# Verify the installed version is at least 3.11.4
node -e "console.log(require('vm2/package.json').version)"

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.