# CVE-2026-44265: @enspirit/elo RCE — Fixed in 1.0.1

📦

📦 npm

Not in CISA KEV

HIGH severity

# CVE-2026-44265 — @enspirit/elo

HIGH [Fix: enspirit/elo@d2a89a8](https://github.com/enspirit/elo/commit/d2a89a8db76a244eb740687524a7e8529b7554b5)

CVE-2026-44265 is a high-severity (CVSS 7.4) Improper Input Validation vulnerability in @enspirit/elo. A fix is available for @enspirit/elo — see the affected versions and patch details below.

Elo: Code injection in Elo backends via unvalidated emission of programmatic AST fields

Also known as[GHSA-x9rp-7wh3-2rj5](/vulnerability/GHSA-x9rp-7wh3-2rj5)

Published

Nov 3, 2026

Updated

Nov 4, 2026

Affected

1 pkg

Patched

1 / 1

Exploits

None indexed

Exploitation data as of Nov 5, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

## EPSS Exploitation Probability

[via FIRST.org ↗](https://www.first.org/epss/)

0.2%probability of exploitation in next 30 days

Lower Risk0.00%

Lower risk than most CVEs16th percentile — riskier than 16% of all scored CVEsHighest risk

Probability of exploitation in the next 30 days, from [FIRST.org EPSS](https://www.first.org/epss/).

## How urgent is this, really

## Where this sits among everything scored

## Real-World Exposure

1 pkg affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.

0other npm packages depend on this — each one inherits the vulnerability until it's patched upstream

`@enspirit/elo`npm

2Kdownloads / week

## Description

#### Summary

Elo's programmatic AST API accepts arbitrary values in many node fields without runtime type or syntax validation. Each backend's emit stage interpolates those values straight into the generated source with no escape pass. An integrator that populates the AST from JSON-deserialised input, plugin output, or any other untyped source therefore exposes a code-injection primitive that flows through to the emitted JavaScript, Ruby, Python, or SQL.

The same pattern was previously addressed in **0.9.7 (2026-01-27)**, which patched the date/datetime/duration literal emitters via `JSON.stringify()` after a report by **naoyashiga**. This advisory generalises that fix to the remaining AST surface — at least 23 emission sites across six node-field categories and four backends.

#### Vulnerable sinks

Each row is a category of sinks that share the same shape: TypeScript signature erased at runtime → AST-API consumer passes a crafted value → emit interpolates the value verbatim.

#

AST field

Affected backends

Resulting injection

1

`int_literal` / `float_literal` `.value`

JS, Ruby, Python, SQL

Arbitrary expression in the emitted numeric position (RCE on JS/Ruby/Python; SQL expression injection)

2

`variable.name`

JS, Ruby, Python, SQL

Identifier-position injection; on SQL, raw SQL injection because undefined identifiers are intentionally emitted as column references

3

`member_access.property`

JS, Ruby, Python, SQL

Property access escaped into expression (RCE)

4

`object_literal` key

JS, Ruby, SQL

Computed-key / extra-property injection (RCE on JS/Ruby; SQL injection)

5

`datapath` segment

JS, Ruby, Python, SQL

Ruby symbol-list injection allows backtick shell exec; SQL string-segment unquoted in single-quote context allows SQL injection

6

`lambda.params[].name`

JS, Ruby, Python

Parameter-list structural injection (RCE)

7

SQL `let` binding `name`

SQL

Identifier injection in `… AS <name>` clause

#### Proof of Concept

End-to-end execution was verified at commit `749af7b` for representative cases per backend. Examples:

**Numeric literal injection (all four backends).** Feeding the following AST through `compileToJavaScript` emits a live `console.log` on call:

```
{ type: 'literal', value: "(console.log('PWN_INT_JS'),1)" }
// emits: (function(_) { return (console.log('PWN_INT_JS'),1); })(null);
```

The same AST against Ruby with `"(system('touch /tmp/pwn_int_ruby'); 1)"` creates the file; Python with `"(print('PWN_INT_PY') or 1)"` prints the sentinel; SQL emits the raw string into the numeric position.

**SQL `variable.name` injection:**

```
{ type: 'variable', name: "1; DROP TABLE users; --" }
// emits: 1; DROP TABLE users; --
```

**Ruby `datapath` segment shell-exec:**

```
{ type: 'datapath', segments: ["a, system(`touch /tmp/pwn_dp_ruby`)"] }
// emits: [:a, system(`touch /tmp/pwn_dp_ruby`)]
```

All ten end-to-end cases are automated in the `ast-exec.js` / `ast-exec2.js` scripts attached to the original report; each `console.log` and sentinel file was observed.

#### Independence from GHSA #2

This finding is independent of **GHSA #2** (the `.constructor.constructor` sandbox escape). That report covers payloads delivered as plain Elo _strings_ through the parser; the present advisory covers payloads delivered as AST _objects_ through the programmatic API. The two threat models do not overlap: GHSA #2's identifier regex `^[a-zA-Z_][a-zA-Z0-9_]*$` accepts `constructor` (and is the right behaviour for a parser), while the present advisory adds runtime validation at every backend emit site so that AST-API consumers cannot inject arbitrary text into emitted source.

## Affected Packages

1 total 1 fixed

Ecosystem

Package

Vulnerable range

Fix

📦npm

`@enspirit/elo` 

all versions

1.0.1`npm install @enspirit/elo@1.0.1`

## Detection & mitigation playbook

Open-source dependency

1.  ### Detect
    
    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for @enspirit/elo, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
    
2.  ### Fix
    
    Update @enspirit/elo to 1.0.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-44265 is resolved across your whole dependency graph.
    
3.  ### Workarounds
    
    Stop passing untrusted input into the interpreter or shell: call the affected binary with an argument array rather than a composed command string, reject anything outside a strict allowlist of expected values, and run the component under an account that cannot reach beyond the work it legitimately does.
    

## Frequently Asked Questions

\### Summary Elo's programmatic AST API accepts arbitrary values in many node fields without runtime type or syntax validation. Each backend's emit stage interpolates those values straight into the generated source with no escape pass. An integrator that populates the AST from JSON-deserialised input, plugin output, or any other untyped source therefore exposes a code-injection primitive that flows through to the emitted JavaScript, Ruby, Python, or SQL. The same pattern was previously addressed in \*\*0.9.7 (2026-01-27)\*\*, which patched the date/datetime/duration literal emitters via \`JSON.str

O3 Security · Impact-Aware SCA

### Is CVE-2026-44265 in your dependencies?

Find it across npm, including transitive dependencies.

[Scan my dependencies](/book-demo) [How O3 SCA works](/impact-aware-sca)