β Back to CVE List
CVE-2026-47141NVD
Description
## Summary
`NodeVM` exposes some process-wide observability builtins when they are allowed through `require.builtin`.
The following builtins are not blocked by the dangerous builtin denylist:
```text
diagnostics_channel
async_hooks
perf_hooks
```
These modules are process-wide, not sandbox-local. Sandboxed code can use them to observe host application data across the vm2 boundary.
**Note**: It is a host data exposure issue. The impact depends on whether the host application allows these builtins and uses HTTP, async request context, diagnostics channels, or performance marks in the same process.
## Details
Non-denied builtins are exposed to the sandbox through `lib/builtin.js`:
```js
builtins.set(key, special ? special : vm => vm.readonly(hostRequire(key)));
```
`diagnostics_channel`, `async_hooks`, and `perf_hooks` are not denied. These modules expose host process state rather than sandbox-local state.
Confirmed examples:
1. `diagnostics_channel` lets sandboxed code subscribe to Node.js HTTP diagnostic channels such as `http.server.request.start`. The sandbox receives host HTTP request objects and can read headers such as `Authorization` or session tokens.
2. `async_hooks.executionAsyncResource()` lets sandboxed code read the current host `AsyncResource`. If the host stores request/user data on that resource, the sandbox can read it.
3. `perf_hooks.performance.getEntriesByType('mark')` lets sandboxed code read host performance timeline entries.
## PoC
Run from the vm2 repository root:
```bash
node poc/observability-builtins-info-leak.js
```
[observability-builtins-info-leak.js](https://github.com/user-attachments/files/27571259/observability-builtins-info-leak.js)
The PoC uses only the specific builtin being tested in each section.
It confirms:
```text
diagnostics_channel: sandbox reads host HTTP request headers
async_hooks: sandbox reads host AsyncResource data
perf_hooks: sandbox reads host performance mark names
```
Example impact from the PoC:
```text
authorization: Bearer HOST_HTTP_SECRET_...
x-session-token: HOST_HTTP_SECRET_...
```
These values are sent to a host HTTP server, but the sandbox reads them through `diagnostics_channel`.
<img width="997" height="566" alt="Screenshot 2026-05-10 at 1 13 20β―PM" src="https://github.com/user-attachments/assets/36a7d600-8b53-4bfe-ab06-4e6dcfad5015" />
## Impact
An attacker who can run untrusted JavaScript inside `NodeVM` with affected builtin settings can observe data from the host process.
In a real application, this may expose HTTP request headers, authorization tokens, session tokens, request context values, user identifiers, or other sensitive diagnostics data from the host application or from other users.
## Suggested fix
Treat process-wide observability modules as dangerous builtins for untrusted sandboxes.
At minimum, consider blocking:
```text
diagnostics_channel
async_hooks
perf_hooks
```
These modules are not sandbox-local and can expose host process state across the vm2 boundary.
`NodeVM` exposes some process-wide observability builtins when they are allowed through `require.builtin`.
The following builtins are not blocked by the dangerous builtin denylist:
```text
diagnostics_channel
async_hooks
perf_hooks
```
These modules are process-wide, not sandbox-local. Sandboxed code can use them to observe host application data across the vm2 boundary.
**Note**: It is a host data exposure issue. The impact depends on whether the host application allows these builtins and uses HTTP, async request context, diagnostics channels, or performance marks in the same process.
## Details
Non-denied builtins are exposed to the sandbox through `lib/builtin.js`:
```js
builtins.set(key, special ? special : vm => vm.readonly(hostRequire(key)));
```
`diagnostics_channel`, `async_hooks`, and `perf_hooks` are not denied. These modules expose host process state rather than sandbox-local state.
Confirmed examples:
1. `diagnostics_channel` lets sandboxed code subscribe to Node.js HTTP diagnostic channels such as `http.server.request.start`. The sandbox receives host HTTP request objects and can read headers such as `Authorization` or session tokens.
2. `async_hooks.executionAsyncResource()` lets sandboxed code read the current host `AsyncResource`. If the host stores request/user data on that resource, the sandbox can read it.
3. `perf_hooks.performance.getEntriesByType('mark')` lets sandboxed code read host performance timeline entries.
## PoC
Run from the vm2 repository root:
```bash
node poc/observability-builtins-info-leak.js
```
[observability-builtins-info-leak.js](https://github.com/user-attachments/files/27571259/observability-builtins-info-leak.js)
The PoC uses only the specific builtin being tested in each section.
It confirms:
```text
diagnostics_channel: sandbox reads host HTTP request headers
async_hooks: sandbox reads host AsyncResource data
perf_hooks: sandbox reads host performance mark names
```
Example impact from the PoC:
```text
authorization: Bearer HOST_HTTP_SECRET_...
x-session-token: HOST_HTTP_SECRET_...
```
These values are sent to a host HTTP server, but the sandbox reads them through `diagnostics_channel`.
<img width="997" height="566" alt="Screenshot 2026-05-10 at 1 13 20β―PM" src="https://github.com/user-attachments/assets/36a7d600-8b53-4bfe-ab06-4e6dcfad5015" />
## Impact
An attacker who can run untrusted JavaScript inside `NodeVM` with affected builtin settings can observe data from the host process.
In a real application, this may expose HTTP request headers, authorization tokens, session tokens, request context values, user identifiers, or other sensitive diagnostics data from the host application or from other users.
## Suggested fix
Treat process-wide observability modules as dangerous builtins for untrusted sandboxes.
At minimum, consider blocking:
```text
diagnostics_channel
async_hooks
perf_hooks
```
These modules are not sandbox-local and can expose host process state across the vm2 boundary.