GHSA-33r5-xmm8-v6x5: Elo JavaScript emitter has sandbox escape to arbitrary Node.js / browser code execution via unfiltered `.constructor` member access

  • Severity: CRITICAL
  • CVE: CVE-2026-44267
  • Ecosystems: npm
  • Packages: @enspirit/elo

### Summary

An unauthenticated attacker who controls a string passed to any Elo JavaScript-emission path — `defaultFormats.elo.parse()`, the `bin/elo` CLI, or the live browser playground at `elo-lang.org/try` — can execute arbitrary code in the host JavaScript runtime. A payload built from the `.constructor.constructor` chain compiles, without modification, to a live `Function` invocation in the emitted JavaScript, escaping any sandbox assumption around “Elo is a safe data/DSL language.”

### Vulnerable sink and root cause

Three interacting sites in `src/` produce the bug at commit `749af7b`:

1. **`src/transform.ts:144–158`** — the `member_access` handler allows access on types `any`, `object`, or `array` without filtering the property name. This is the only place an integrator could have plugged a denylist.
2. **`src/compilers/javascript.ts:210`** — the JS emitter writes `${objectExpr}.${ir.property}` verbatim into the output, so any property name that survives the transform step flows unescaped into emitted JavaScript.
3. **`src/parser.ts:163–170, 748–750`** — the parser accepts `constructor` (and other JS meta-property names) as an ordinary identifier, so `.constructor` clears type-checking without triggering any warning.

Combined, the Elo expression `({}).constructor.constructor(‘…’)()` compiles to a live `Function(‘…’)()` call in the emitted JS, executing in the realm of whichever sink runs the compiled code.

### Attack surfaces

All three surfaces share the same ro…

Source: GitHub Security Advisories · 2026-11-03