CVE-2026-34217
SandboxJS has a Sandbox Escape via Prop Object Leak in New Handler
SandboxJS is a JavaScript sandboxing library. Prior to 0.8.36, a scope modification vulnerability exists in @nyariv/sandboxjs. The vulnerability allows untrusted sandboxed code to leak internal interpreter objects through the new operator, exposing sandbox scope objects in the scope hierarchy to untrusted code; an unexpected and undesired exploit. While this could allow modifying scopes inside the sandbox, code evaluation remains sandboxed and prototypes remain protected throughout the execution. 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
- Low
- Integrity
- Low
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
6.9
SandboxJS has a Sandbox Escape via Prop Object Leak in New Handler
SandboxJS is a JavaScript sandboxing library. Prior to 0.8.36, a scope modification vulnerability exists in @nyariv/sandboxjs. The vulnerability allows untrusted sandboxed code to leak internal interpreter objects through the new operator, exposing sandbox scope objects in the scope hierarchy to untrusted code; an unexpected and undesired exploit. While this could allow modifying scopes inside the sandbox, code evaluation remains sandboxed and prototypes remain protected throughout the execution. This vulnerability is fixed in 0.8.36.
- Record
CVE-2026-34217- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-668
- Updated
- 2026-11-02
EUVDEUVD-2026-19301
6.9
SandboxJS is a JavaScript sandboxing library. Prior to 0.8.36, a scope modification vulnerability exists in @nyariv/sandboxjs. The vulnerability allows untrusted sandboxed code to leak internal interpreter objects through the new operator, exposing sandbox scope objects in the scope hierarchy to untrusted code; an unexpected and undesired exploit. While this could allow modifying scopes inside the sandbox, code evaluation remains sandboxed and prototypes remain protected throughout the execution. This vulnerability is fixed in 0.8.36.
- Record
EUVD-2026-19301- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-hg73-4w7g-q96w
6.9
SandboxJS: Sandbox Escape via Prop Object Leak in New Handler
Description
A scope modification vulnerability exists in @nyariv/sandboxjs version 0.8.35 and below. The vulnerability allows untrusted sandboxed code to leak internal interpreter objects through the new operator, exposing sandbox scope objects in the scope hierarchy to untrusted code; an unexpected and undesired exploit. While this could allow modifying scopes inside the sandbox, code evaluation remains sandboxed and prototypes remain protected throughout the execution.
Vulnerable Code Location
Primary: The New Operator Handler
File: src/executor.ts, lines 1275–1280
addOps<new (...args: unknown[]) => unknown, unknown[]>(
LispType.New,
({ done, a, b, context }) => {
if (!context.ctx.globalsWhitelist.has(a) && !context.ctx.sandboxedFunctions.has(a)) {
throw new SandboxAccessError(`Object construction not allowed: ${a.constructor.name}`);
}
done(undefined, new a(...b)); // ← b is NOT sanitized, return is NOT sanitized
},
);
This handler has two missing sanitization steps:
-
Arguments (
b) are not passed throughvalueOrProp()— Constructor arguments contain rawPropobjects (internal interpreter wrappers) instead of extracted values. -
Return value is not passed through
getGlobalProp()orsanitizeArray()— The constructed object is returned directly to the execution tree without any sanitization.
Comparison: The Call Handler (Correctly Implemented)
File: src/executor.ts, lines 493–605
addOps<unknown, Lisp[], any>(LispType.Call, ({ done, a, b, obj, context }) => {
// ...
const vals = b
.map((item) => {
if (item instanceof SpreadArray) {
return [...item.item];
} else {
return [item];
}
})
.flat()
.map((item) => valueOrProp(item, context)); // ← Arguments ARE sanitized
// ...
let ret = evl ? evl(obj.context[obj.prop], ...vals) : (obj.context[obj.prop](...vals));
ret = getGlobalProp(ret, context) || ret; // ← Return IS sanitized
sanitizeArray(ret, context); // ← Return IS sanitized
done(undefined, ret);
});
The Call handler correctly sanitizes both arguments (via valueOrProp) and return values (via getGlobalProp and sanitizeArray). The New handler does neither.
Why This Is Vulnerable
Step 1: What is a Prop Object?
The sandbox interpreter wraps every value access in a Prop object (defined at src/utils.ts, lines 565–582). A Prop has:
class Prop {
context: any; // The object the property belongs to
prop: PropertyKey; // The property name
isConst: boolean;
isGlobal: boolean;
isVariable: boolean;
}
When sandboxed code accesses a variable like isNaN, the interpreter creates Prop(scope.allVars, 'isNaN'). The context field is a direct reference to the scope's variable storage object.
Step 2: What is in scope.allVars?
At the global scope level, scope.allVars is the same object as options.globals — the SAFE_GLOBALS object containing:
{
globalThis: <real globalThis>,
Function: <real Function constructor>,
eval: <real eval function>,
console: { log: console.log, ... },
Array, Object, Map, Set, Promise, Date, Error, RegExp,
isNaN, parseInt, parseFloat, ...
}
These are the real host JavaScript objects. The sandbox normally protects them by intercepting reads through the Prop handler and replacing dangerous ones via the evals Map.
Step 3: How the Prop Leaks Through new
When sandboxed code executes new Constructor(someVariable):
- The interpreter evaluates
someVariable— this produces aPropobject:Prop(scope.allVars, 'someVariable') - The
Newhandler receives thisPropas-is in thebarray (novalueOrProp()call) new Constructor(...[Prop])passes the rawPropobject to the constructor function- Inside the constructor, the
Propis received as a named parameter 5.…
- Record
GHSA-hg73-4w7g-q96w- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-668
- Updated
- 2026-11-02
NVD
6.9
SandboxJS is a JavaScript sandboxing library. Prior to 0.8.36, a scope modification vulnerability exists in @nyariv/sandboxjs. The vulnerability allows untrusted sandboxed code to leak internal interpreter objects through the new operator, exposing sandbox scope objects in the scope hierarchy to untrusted code; an unexpected and undesired exploit. While this could allow modifying scopes inside the sandbox, code evaluation remains sandboxed and prototypes remain protected throughout the execution. This vulnerability is fixed in 0.8.36.
- Record
CVE-2026-34217- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/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
- 7.2 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N - Weakness
- CWE-668
- Updated
- 2026-11-02
OSVGHSA-hg73-4w7g-q96w
6.9
SandboxJS: Sandbox Escape via Prop Object Leak in New Handler
Description
A scope modification vulnerability exists in @nyariv/sandboxjs version 0.8.35 and below. The vulnerability allows untrusted sandboxed code to leak internal interpreter objects through the new operator, exposing sandbox scope objects in the scope hierarchy to untrusted code; an unexpected and undesired exploit. While this could allow modifying scopes inside the sandbox, code evaluation remains sandboxed and prototypes remain protected throughout the execution.
Vulnerable Code Location
Primary: The New Operator Handler
File: src/executor.ts, lines 1275–1280
addOps<new (...args: unknown[]) => unknown, unknown[]>(
LispType.New,
({ done, a, b, context }) => {
if (!context.ctx.globalsWhitelist.has(a) && !context.ctx.sandboxedFunctions.has(a)) {
throw new SandboxAccessError(`Object construction not allowed: ${a.constructor.name}`);
}
done(undefined, new a(...b)); // ← b is NOT sanitized, return is NOT sanitized
},
);
This handler has two missing sanitization steps:
-
Arguments (
b) are not passed throughvalueOrProp()— Constructor arguments contain rawPropobjects (internal interpreter wrappers) instead of extracted values. -
Return value is not passed through
getGlobalProp()orsanitizeArray()— The constructed object is returned directly to the execution tree without any sanitization.
Comparison: The Call Handler (Correctly Implemented)
File: src/executor.ts, lines 493–605
addOps<unknown, Lisp[], any>(LispType.Call, ({ done, a, b, obj, context }) => {
// ...
const vals = b
.map((item) => {
if (item instanceof SpreadArray) {
return [...item.item];
} else {
return [item];
}
})
.flat()
.map((item) => valueOrProp(item, context)); // ← Arguments ARE sanitized
// ...
let ret = evl ? evl(obj.context[obj.prop], ...vals) : (obj.context[obj.prop](...vals));
ret = getGlobalProp(ret, context) || ret; // ← Return IS sanitized
sanitizeArray(ret, context); // ← Return IS sanitized
done(undefined, ret);
});
The Call handler correctly sanitizes both arguments (via valueOrProp) and return values (via getGlobalProp and sanitizeArray). The New handler does neither.
Why This Is Vulnerable
Step 1: What is a Prop Object?
The sandbox interpreter wraps every value access in a Prop object (defined at src/utils.ts, lines 565–582). A Prop has:
class Prop {
context: any; // The object the property belongs to
prop: PropertyKey; // The property name
isConst: boolean;
isGlobal: boolean;
isVariable: boolean;
}
When sandboxed code accesses a variable like isNaN, the interpreter creates Prop(scope.allVars, 'isNaN'). The context field is a direct reference to the scope's variable storage object.
Step 2: What is in scope.allVars?
At the global scope level, scope.allVars is the same object as options.globals — the SAFE_GLOBALS object containing:
{
globalThis: <real globalThis>,
Function: <real Function constructor>,
eval: <real eval function>,
console: { log: console.log, ... },
Array, Object, Map, Set, Promise, Date, Error, RegExp,
isNaN, parseInt, parseFloat, ...
}
These are the real host JavaScript objects. The sandbox normally protects them by intercepting reads through the Prop handler and replacing dangerous ones via the evals Map.
Step 3: How the Prop Leaks Through new
When sandboxed code executes new Constructor(someVariable):
- The interpreter evaluates
someVariable— this produces aPropobject:Prop(scope.allVars, 'someVariable') - The
Newhandler receives thisPropas-is in thebarray (novalueOrProp()call) new Constructor(...[Prop])passes the rawPropobject to the constructor function- Inside the constructor, the
Propis received as a named parameter 5.…
- Record
GHSA-hg73-4w7g-q96w- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-668
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@nyariv/sandboxjsnpm |
through 0.8.35 | 0.8.36 |
@nyariv/sandboxjsnpm |
before 0.8.36 | 0.8.36 |
History
| Recorded | Changed | Sources |
|---|---|---|
| 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-34217 is a medium vulnerability (CVSS 6.9) 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.30%, the 23rd percentile. Fixed in @nyariv/sandboxjs 0.8.36.
References
Left out here: the rest of 2 source descriptions. The JSON record has them.