Live › vulnerability › CVE-2026-44266
The Elo compiler's Ruby target writes string literals into Ruby double-quoted strings without escaping the # character, so a #{...} sequence in Elo source becomes live Ruby code. An attacker who can supply Elo source compiled to Ruby can run arbitrary shell commands through backticks.
Summary written from the sources below. Check the originals before acting.
First seen by InfraStack 2026-11-03 17:52 UTC, 1h before NVD. All times on this page are UTC.
Teams that compile Elo to Ruby using the library API or the eloc CLI on Elo source that includes untrusted input, such as a rule engine, configuration DSL or form builder that accepts user-supplied strings. Projects that only compile Elo to JavaScript, Python or SQL, or that only compile trusted Elo source, are not exposed by this flaw.
| Product | Ecosystem | Affected | Fixed in |
|---|---|---|---|
| @enspirit/elo | npm | <= 1.0.0 | 1.0.1 |
@enspirit/elo in your project lockfile or with npm ls @enspirit/elo.eloc -t ruby or the Ruby emission API) on Elo source you do not fully control.@enspirit/elo fixed in 1.0.1; affected versions are <= 1.0.0.Each row is the first time that source carried this signal. The analyst’s rows are its own findings.
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.
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 at src/parser.ts:1339–1348 accepts single-quoted Elo strings as constraint labels, a label such as '#{ `id` }' flows unchanged into the emitted Ruby.
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) |
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.
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.
This page as .md · .json · in your agent: get_signal("CVE-2026-44266")
GitHub Advisory Database, CC-BY 4.0 · NVD data is provided by NIST and is public domain. Posts quoted belong to their authors.