CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-25881

Dirty Laundry: Escaping SandboxJS via Array Laundering

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 10, 2026·6 min read·55 visits

Executive Summary (TL;DR)

SandboxJS failed to persist security tags when objects were placed into array literals. Attackers could wrap a global object (like `Array.prototype`) in an array, retrieve it, and receive a 'clean' reference, allowing them to pollute the host environment.

A critical sandbox escape vulnerability in `@nyariv/sandboxjs` allows malicious code to bypass the 'isGlobal' protection flag by laundering host references through array literals. This seemingly innocuous action strips security metadata, granting attackers write access to critical host prototypes (CWE-1321) and leading to potential Remote Code Execution (RCE).

The Hook: A Playground with Landmines

JavaScript sandboxing is like trying to hold water in a sieve. The language is so dynamic, so mutable, and so interconnected that creating a truly isolated environment is a Herculean task. @nyariv/sandboxjs attempts this by parsing and executing JS in a controlled scope, wrapping objects to track permissions. The goal is simple: let users run untrusted code without burning down the server.

However, the library relies on a concept called 'taint tracking'—specifically, an isGlobal flag attached to wrappers around sensitive host objects (like window, process, or Array.prototype). If isGlobal is true, the sandbox blocks write access. It's a 'Do Not Touch' sticker on the museum exhibits.

The problem with stickers is that they fall off if you handle the merchandise too much. In CVE-2026-25881, we found a way to peel that sticker off simply by putting the object in a box and taking it back out.

The Flaw: Laundering the Taint

The vulnerability lies in how the sandbox handles intermediate values, specifically Array Literals. When the sandbox executes code, it wraps every object in a Prop class. This class holds the isGlobal boolean. If you try to access Array.prototype directly, the sandbox hands you a wrapper with isGlobal: true.

Here is where the logic breaks down. When you define an array literal like [Array.prototype], the sandbox's CreateArray operation extracts the raw value from the wrapper to populate the new array. It effectively says, 'Okay, you want an array containing this object? Here is the object.' It forgets to attach the 'Do Not Touch' note to the array's internal storage of that object.

When you subsequently access that index (e.g., arr[0]), the sandbox creates a new wrapper for the retrieved value. Since the retrieval didn't come from a known global lookup (it just came from some random array), the new wrapper defaults to isGlobal: false. The object has been 'laundered'. It is now a clean, writable reference to the host's actual Array.prototype.

The Code: Identity vs. Origin

The root cause was a philosophical error in the code: trusting the path of access rather than the identity of the object. The fix introduced in version 0.8.31 completely shifts this paradigm.

The Vulnerable Logic (Conceptual):

// Old way: Relying on metadata passing
function getProperty(obj, key) {
  const value = obj[key];
  // If obj was a random array, we assume 'value' is safe.
  return new Prop(value, { isGlobal: false }); 
}

The Fix (Identity Check): The patch introduces a helper getGlobalProp that runs on every property access. It checks the value itself against a list of known dangerous globals.

// src/executor.ts
function getGlobalProp(val: unknown, context: IExecContext, prop?: Prop) {
  if (!val) return;
  
  // CRITICAL: Check if the value IS the global object
  if (val === globalThis) {
    return new Prop({ [p]: context.ctx.sandboxGlobal }, p, prop?.isConst, false, prop?.isVariable);
  }
 
  // Check if value is a known host function or prototype
  const e = isFunc && context.evals.get(val);
  if (e) {
    // FORCE the protection flag back on
    return new Prop({ [p]: e }, p, prop?.isConst, true, prop?.isVariable);
  }
}

By validating the identity of val against the context's allowlist (context.evals), the sandbox re-applies the handcuffs even if the object was laundered through a dozen arrays.

The Exploit: Step-by-Step Escape

Exploiting this is embarrassingly simple. We don't need complex heap manipulation or race conditions. We just need to move an object from Point A to Point B.

The Attack Chain:

  1. Target Acquisition: We need a reference to a host prototype. Array.prototype is perfect because it's available everywhere.
  2. The Wash Cycle: We wrap it in an array literal.
  3. The Rinse: We read it back out. The sandbox sees this as "just an item from a user array" and grants us a writable wrapper.
  4. Pollution: We write to the prototype. Because JS is prototype-based, this modifies the Array definition for the entire host process.

The PoC:

// Inside the sandbox
const laundryBasket = [Array.prototype]; 
const cleanShirt = laundryBasket[0]; // The 'isGlobal' flag is gone now
 
// Add a property to the actual host Array prototype
cleanShirt.polluted = "I am in your walls";
 
// Verification (in Host)
// console.log([].polluted) -> "I am in your walls"

If the host application later runs code like const cmd = userOptions.cmd || 'default', and we've polluted Object.prototype to inject a malicious command, we achieve Remote Code Execution.

The Impact: From Pollution to RCE

Why is this rated Critical (9.1)? Because SandboxJS is often used to run user-submitted scripts in SaaS platforms, rule engines, or plugin systems. Breaking out of the sandbox destroys the security model entirely.

Once an attacker has Prototype Pollution on the host, they can usually escalate to RCE. Common patterns include:

  • Template Injection: Polluting properties used by template engines (e.g., outputFunctionName in EJS).
  • Process Spawning: Polluting shell or env options passed to child_process.exec or spawn.
  • DoS: Overwriting toString or valueOf to throw errors or enter infinite loops.

This isn't just a data leak; it's full server compromise if the host application uses any standard libraries vulnerable to pollution gadgets.

The Fix: Trust No One

The remediation is straightforward: Update to version 0.8.31.

The patch forces the sandbox to be paranoid. It no longer trusts that a value is safe just because it came from a safe place. It checks the ID card of every object, every time it is accessed.

If you cannot update immediately, you are essentially running code on the host with extra steps. A temporary mitigation (though ugly) would be to freeze all prototypes in the host environment before starting the sandbox:

// Host-side mitigation
Object.freeze(Object.prototype);
Object.freeze(Array.prototype);
// ... repeat for all built-ins

This might break other dependencies, but it stops the bleeding until you can patch.

Official Patches

NyarivCommit fixing the escape vulnerability

Fix Analysis (1)

Technical Appendix

CVSS Score
9.1/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H

Affected Systems

@nyariv/sandboxjs < 0.8.31

Affected Versions Detail

Product
Affected Versions
Fixed Version
@nyariv/sandboxjs
nyariv
< 0.8.310.8.31
AttributeDetail
CWE IDCWE-1321
CWE NamePrototype Pollution
CVSS Score9.1 (Critical)
Attack VectorNetwork (AV:N)
Exploit MaturityPoC Available
ImpactSandbox Escape / RCE

MITRE ATT&CK Mapping

T1659Content Injection
Defense Evasion
T1211Exploitation for Defense Evasion
Defense Evasion
CWE-1321
Prototype Pollution

Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')

Known Exploits & Detection

GitHub AdvisoryOfficial advisory containing PoC details

Vulnerability Timeline

Fix committed to repository
2026-02-08
GitHub Advisory published
2026-02-09
Version 0.8.31 released
2026-02-09

References & Sources

  • [1]GHSA-ww7g-4gwx-m7wj
  • [2]SandboxJS Repository

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 1 hour ago•CVE-2026-54550
7.4

CVE-2026-54550: Path Traversal Vulnerability in IzPack Installer Unpacker

IzPack versions 5.2.6 and earlier are vulnerable to path traversal via UnpackerBase.unpack(). The vulnerability allows unauthenticated attackers to write arbitrary files to the host filesystem during the installation process by crafting malicious installer packages containing directory traversal sequences.

Alon Barad
Alon Barad
1 views•4 min read
•about 2 hours ago•CVE-2026-54511
8.6

CVE-2026-54511: Log Injection and Structured Data Key Injection in @logtape/syslog

CVE-2026-54511 is a critical security vulnerability in the @logtape/syslog package, which serves as the syslog sink for the LogTape logging library. The flaw is caused by a failure to neutralize C0 control characters in structured data values and to validate keys against RFC 5424 SD-NAME specifications when structured data output is enabled. Remote attackers can leverage this defect to terminate TCP syslog frames and append completely forged syslog records to downstream collectors, compromising the integrity of audit trails and SIEM databases.

Alon Barad
Alon Barad
2 views•6 min read
•about 3 hours ago•CVE-2026-54786
5.0

CVE-2026-54786: Host File Descriptor Exhaustion in Wasmtime WASIp1 Runtime

A resource leak vulnerability in Wasmtime's WASIp1 native implementation of the fd_renumber system call allows guest WebAssembly applications to leak host file descriptors, ultimately leading to process-wide Denial of Service (DoS) via resource exhaustion.

Amit Schendel
Amit Schendel
2 views•8 min read
•about 4 hours ago•CVE-2026-55688
4.0

CVE-2026-55688: Cookie Tossing / Cookie Injection Vulnerability in AsyncHttpClient

CVE-2026-55688 is a medium-severity cookie injection vulnerability in the AsyncHttpClient (AHC) library. Due to a failure to validate the domain attribute against the origin server during cookie handling, applications using a shared AHC client instance are vulnerable to cookie-tossing attacks.

Alon Barad
Alon Barad
3 views•5 min read
•about 5 hours ago•GHSA-93QJ-5Q5V-3C2H
0.0

GHSA-93QJ-5Q5V-3C2H: Embedded Malicious Code in pantheon-agents PyPI Packages

A supply-chain compromise affecting the pantheon-agents PyPI package, where versions 0.6.1 and 0.6.2 were uploaded with malicious payloads that exfiltrate sensitive environment variables and credentials.

Alon Barad
Alon Barad
6 views•5 min read
•about 6 hours ago•GHSA-X287-5C68-36WP
7.1

GHSA-X287-5C68-36WP: Broken Object-Level Authorization in OpenWISP IPAM Django Admin

A broken object-level authorization (BOLA) vulnerability exists in the Django Admin custom export view of OpenWISP IPAM. This flaw allows a multi-tenancy restricted staff user to export subnets and associated IP addresses belonging to different organizations by supplying a targeted subnet identifier in the export request.

Alon Barad
Alon Barad
3 views•6 min read