CVE-2026-44266
Elo: Remote Code Execution in Elo Ruby backend via unescaped `#{...}` interpolation in emitted string literals and subtype-constraint labels
Elo is a purely functional expression language for no-code tools. Prior to 1.0.1, the Ruby backend in src/compilers/ruby.ts embeds attacker-controlled text in Ruby double-quoted strings without escaping #, so Ruby interpolation forms in the string-literal emitter or the labelled subtype-constraint branch become executable Ruby. The affected entry points include the /try playground with the Ruby target, bin/eloc -t ruby -x, and defaultFormats.elo.parse() followed by Ruby emission. A failing labelled subtype constraint evaluates its message, while an ordinary string literal is evaluated when the compiled Ruby runs, allowing Ruby code and shell command execution through backticks. JavaScript, Python, and SQL emission are not affected by this Ruby-specific path. This issue is fixed in version 1.0.1.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
9.8
Elo: Remote Code Execution in Elo Ruby backend via unescaped `#{...}` interpolation in emitted string literals and subtype-constraint labels
Elo is a purely functional expression language for no-code tools. Prior to 1.0.1, the Ruby backend in src/compilers/ruby.ts embeds attacker-controlled text in Ruby double-quoted strings without escaping #, so Ruby interpolation forms in the string-literal emitter or the labelled subtype-constraint branch become executable Ruby. The affected entry points include the /try playground with the Ruby target, bin/eloc -t ruby -x, and defaultFormats.elo.parse() followed by Ruby emission. A failing labelled subtype constraint evaluates its message, while an ordinary string literal is evaluated when the compiled Ruby runs, allowing Ruby code and shell command execution through backticks. JavaScript, Python, and SQL emission are not affected by this Ruby-specific path. This issue is fixed in version 1.0.1.
- Record
CVE-2026-44266- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-94, CWE-116, CWE-1336
- Updated
- 2026-11-03
EUVDEUVD-2026-116110
9.8
Elo is a purely functional expression language for no-code tools. Prior to 1.0.1, the Ruby backend in src/compilers/ruby.ts embeds attacker-controlled text in Ruby double-quoted strings without escaping #, so Ruby interpolation forms in the string-literal emitter or the labelled subtype-constraint branch become executable Ruby. The affected entry points include the /try playground with the Ruby target, bin/eloc -t ruby -x, and defaultFormats.elo.parse() followed by Ruby emission. A failing labelled subtype constraint evaluates its message, while an ordinary string literal is evaluated when the compiled Ruby runs, allowing Ruby code and shell command execution through backticks. JavaScript, Python, and SQL emission are not affected by this Ruby-specific path. This issue is fixed in version 1.0.1.
- Record
EUVD-2026-116110- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Updated
- 2026-11-03
GitHub AdvisoriesGHSA-7w38-ggh5-v542
9.8
Elo Ruby backend has Remote Code Execution via unescaped `#{...}` interpolation in emitted string literals and subtype-constraint labels
Summary
Elo's Ruby backend emits attacker-controlled text into Ruby double-quoted strings without escaping the # character. Because # begins Ruby's interpolation sequences — #{expr}, #@ivar, #@@cvar, #$gvar — and any expression wrapped in #{...} may use backticks for shell execution, an Elo program that contains a crafted string literal or a labelled subtype constraint compiles to Ruby that evaluates attacker-chosen Ruby, and through backticks runs attacker-chosen shell commands, at runtime.
The same Elo source compiled to JavaScript, Python, or SQL is benign, so the bug also breaks the cross-target portability guarantee the rest of the compiler honours.
Vulnerable sinks
Two sinks exist in src/compilers/ruby.ts at commit 749af7b:
-
String-literal emitter — lines 180–184. The emitter escapes backslash, double quote, and control characters, but not
#. Any#{...}sequence in an Elo string literal flows straight into the emitted Ruby source. -
Labelled subtype-constraint branch — lines 405–412. The error message passed to
p_fail(p, "...")is wrapped in a Ruby double-quoted string with no escape pass at all. Because the parser atsrc/parser.ts:1339–1348accepts single-quoted Elo strings as constraint labels, a label such as'#{`id`}'flows unchanged into the emitted Ruby.
Attack surfaces
All three surfaces share the same root cause (the missing # escape in the Ruby double-quoted-string emission path) and are addressed by the same patch:
| # | Entry point | Threat model |
|---|---|---|
| 1 | /try playground on elo-lang.org (Ruby target) | 0-click server-side RCE against elo-lang.org infrastructure from a shared PoC URL |
| 2 | bin/eloc -t ruby -x on a CI or DevOps host | RCE on any host that passes Elo strings through the CLI |
| 3 | Library API — defaultFormats.elo.parse() with a Ruby emission step | Ruby RCE for any downstream integrator using Elo as a rule engine, configuration DSL, or form builder DSL (the primary documented use cases) |
Proof of Concept
String-literal sink:
# poc.elo
'RES=#{`id 2>&1`}'
$ eloc -t ruby -x poc.elo
# emitted Ruby contains: "RES=#{`id 2>&1`}"
# running it returns the output of id(1).
Replacing `id 2>&1` with `touch /tmp/pwned` produces a trivially observable filesystem side effect.
Subtype-constraint label sink:
# poc-subtype.elo
let X = Int(i | '#{`touch /tmp/pwned2`}': i > 0) in X(-1)
The predicate fails for -1, causing p_fail(p, "#{...}") to interpolate and execute the backtick command at the Ruby layer.
Both flows are automated in the reproduction script submitted with the original report and were verified against Ruby 3.x.
Root cause
The Ruby-emitter's double-quoted-string escape routine omitted # from its character set, and one emission path (the subtype-constraint label branch) performed no escape pass at all.
- Record
GHSA-7w38-ggh5-v542- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-94, CWE-116, CWE-1336
- Updated
- 2026-11-03
NVD
9.8
Elo is a purely functional expression language for no-code tools. Prior to 1.0.1, the Ruby backend in src/compilers/ruby.ts embeds attacker-controlled text in Ruby double-quoted strings without escaping #, so Ruby interpolation forms in the string-literal emitter or the labelled subtype-constraint branch become executable Ruby. The affected entry points include the /try playground with the Ruby target, bin/eloc -t ruby -x, and defaultFormats.elo.parse() followed by Ruby emission. A failing labelled subtype constraint evaluates its message, while an ordinary string literal is evaluated when the compiled Ruby runs, allowing Ruby code and shell command execution through backticks. JavaScript, Python, and SQL emission are not affected by this Ruby-specific path. This issue is fixed in version 1.0.1.
- Record
CVE-2026-44266- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-94, CWE-116, CWE-1336
- Updated
- 2026-11-03
OSV
9.8
Elo: Remote Code Execution in Elo Ruby backend via unescaped `#{...}` interpolation in emitted string literals and subtype-constraint labels
Elo is a purely functional expression language for no-code tools. Prior to 1.0.1, the Ruby backend in src/compilers/ruby.ts embeds attacker-controlled text in Ruby double-quoted strings without escaping #, so Ruby interpolation forms in the string-literal emitter or the labelled subtype-constraint branch become executable Ruby. The affected entry points include the /try playground with the Ruby target, bin/eloc -t ruby -x, and defaultFormats.elo.parse() followed by Ruby emission. A failing labelled subtype constraint evaluates its message, while an ordinary string literal is evaluated when the compiled Ruby runs, allowing Ruby code and shell command execution through backticks. JavaScript, Python, and SQL emission are not affected by this Ruby-specific path. This issue is fixed in version 1.0.1.
- Record
CVE-2026-44266- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-116, CWE-1336, CWE-94
- Updated
- 2026-11-05
OSVGHSA-7w38-ggh5-v542
9.8
Elo Ruby backend has Remote Code Execution via unescaped `#{...}` interpolation in emitted string literals and subtype-constraint labels
Summary
Elo's Ruby backend emits attacker-controlled text into Ruby double-quoted strings without escaping the # character. Because # begins Ruby's interpolation sequences — #{expr}, #@ivar, #@@cvar, #$gvar — and any expression wrapped in #{...} may use backticks for shell execution, an Elo program that contains a crafted string literal or a labelled subtype constraint compiles to Ruby that evaluates attacker-chosen Ruby, and through backticks runs attacker-chosen shell commands, at runtime.
The same Elo source compiled to JavaScript, Python, or SQL is benign, so the bug also breaks the cross-target portability guarantee the rest of the compiler honours.
Vulnerable sinks
Two sinks exist in src/compilers/ruby.ts at commit 749af7b:
-
String-literal emitter — lines 180–184. The emitter escapes backslash, double quote, and control characters, but not
#. Any#{...}sequence in an Elo string literal flows straight into the emitted Ruby source. -
Labelled subtype-constraint branch — lines 405–412. The error message passed to
p_fail(p, "...")is wrapped in a Ruby double-quoted string with no escape pass at all. Because the parser atsrc/parser.ts:1339–1348accepts single-quoted Elo strings as constraint labels, a label such as'#{`id`}'flows unchanged into the emitted Ruby.
Attack surfaces
All three surfaces share the same root cause (the missing # escape in the Ruby double-quoted-string emission path) and are addressed by the same patch:
| # | Entry point | Threat model |
|---|---|---|
| 1 | /try playground on elo-lang.org (Ruby target) | 0-click server-side RCE against elo-lang.org infrastructure from a shared PoC URL |
| 2 | bin/eloc -t ruby -x on a CI or DevOps host | RCE on any host that passes Elo strings through the CLI |
| 3 | Library API — defaultFormats.elo.parse() with a Ruby emission step | Ruby RCE for any downstream integrator using Elo as a rule engine, configuration DSL, or form builder DSL (the primary documented use cases) |
Proof of Concept
String-literal sink:
# poc.elo
'RES=#{`id 2>&1`}'
$ eloc -t ruby -x poc.elo
# emitted Ruby contains: "RES=#{`id 2>&1`}"
# running it returns the output of id(1).
Replacing `id 2>&1` with `touch /tmp/pwned` produces a trivially observable filesystem side effect.
Subtype-constraint label sink:
# poc-subtype.elo
let X = Int(i | '#{`touch /tmp/pwned2`}': i > 0) in X(-1)
The predicate fails for -1, causing p_fail(p, "#{...}") to interpolate and execute the backtick command at the Ruby layer.
Both flows are automated in the reproduction script submitted with the original report and were verified against Ruby 3.x.
Root cause
The Ruby-emitter's double-quoted-string escape routine omitted # from its character set, and one emission path (the subtype-constraint label branch) performed no escape pass at all.
- Record
GHSA-7w38-ggh5-v542- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-116, CWE-1336, CWE-94
- Updated
- 2026-11-03
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@enspirit/elonpm |
through 1.0.0 | 1.0.1 |
@enspirit/elonpm |
before 1.0.1 | 1.0.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| references | EUVD, NVD, OSV | |
| references | CVE List | |
| published | EUVD, NVD | |
| aliases | EUVD | |
| description, products, published, references, severity, title | CVE List | |
| affected, references | OSV | |
| first indexed | GitHub Advisories |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-44266 is a critical vulnerability (CVSS 9.8) in Enspirit Elo, published November 3, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 1.00%, the 62nd percentile. Fixed in @enspirit/elo 1.0.1.
References
github.com/enspirit/elo/security/advisories/GHSA-7w38-ggh5-v542
github.com/enspirit/elo/commit/51b869963fbe445c18328714a7ccfbd76b21ba38
github.com/enspirit/elo/commit/d2a89a8db76a244eb740687524a7e8529b7554b5
github.com/advisories/GHSA-7w38-ggh5-v542
github.com/CVEProject/cvelistV5/tree/main/cves/2026/44xxx/CVE-2026-44266.json
nvd.nist.gov/vuln/detail/CVE-2026-44266
github.com/enspirit/elo