Dev.to Security 🔐 Cybersecurity 👁 0 📖 3 min read

CVE-2026-44266: CVE-2026-44266: Remote Code Execution in @enspirit/elo Ruby Compiler Backend via Unescaped String Interpolation

CVE-2026-44266: Remote Code Execution in @enspirit/elo Ruby Compiler Backend via Unescaped String Interpolation Vulnerability ID: CVE-2026-44266 CVSS Score: 9.8 Published: 2026-11-03 CVE-2026-44266 (GHSA-7w38-ggh5-v

CVE-2026-44266: Remote Code Execution in @enspirit/elo Ruby Compiler Backend via Unescaped String Interpolation

Vulnerability ID: CVE-2026-44266
CVSS Score: 9.8
Published: 2026-11-03

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.

TL;DR

The @enspirit/elo Ruby compiler backend fails to escape '#' characters in double-quoted string literals and subtype constraint failure messages, enabling arbitrary Ruby code and shell command execution via #{...} string interpolation.

⚠️ Exploit Status: POC

Technical Details

  • Vulnerability Type: Code Injection / Remote Code Execution (CWE-94, CWE-116, CWE-1336)
  • Affected Component: @enspirit/elo Ruby Backend Compiler (src/compilers/ruby.ts)
  • Attack Vector: Network / Untrusted Elo Expression Compilation to Ruby
  • CVSS v3.1 Score: 9.8 Critical (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
  • Patched Version: @enspirit/elo 1.0.1
  • Exploit Status: Functional Proof of Concept (PoC) Published
  • CISA KEV Status: Not Listed

Affected Systems

  • @enspirit/elo (npm package) < 1.0.1
  • Elo CLI (bin/eloc) using the Ruby target (-t ruby)
  • Downstream applications compiling untrusted Elo expressions to Ruby
  • @enspirit/elo: < 1.0.1 (Fixed in: 1.0.1)

Code Analysis

Commit: 51b8699

Introduce escapeRubyDQ helper in src/compilers/ruby.ts to escape '#' and prevent Ruby string interpolation in string literals and subtype constraint labels.

--- a/src/compilers/ruby.ts
+++ b/src/compilers/ruby.ts
@@ -150,6 +150,22 @@ function emitRubyWithHelpers(ir: IRExpr, options: EmitOptions): EmitResult {
   return { code, requiredHelpers };
 }

+/**
+ * Escape a raw string for embedding inside a Ruby double-quoted string literal.
+ * In particular, `#` must be escaped so that `#{...}`, `#@ivar`, `#@@cvar` and
+ * `#$gvar` cannot trigger Ruby string interpolation — otherwise attacker-controlled
+ * text (string literals, constraint labels, etc.) becomes executable code.
+ */
+function escapeRubyDQ(s: string): string {
+  return s
+    .replace(/\\/g, '\\\\')
+    .replace(/#/g, '\\#')
+    .replace(/"/g, '\\"')
+    .replace(/\n/g, '\\n')
+    .replace(/\t/g, '\\t')
+    .replace(/\r/g, '\\r');
+}
+
 /**
  * Emit Ruby code from IR
  */
@@ -177,11 +193,8 @@ function emitRuby(ir: IRExpr, requiredHelpers?: Set<string>, options?: EmitOptio
     case 'null_literal':
       return 'nil';

-    case 'string_literal': {
-      // Ruby double-quoted strings: escape backslash, double quote, and control chars
-      const escaped = ir.value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\t/g, '\\t').replace(/\r/g, '\\r');
-      return `"${escaped}"`;
-    }
+    case 'string_literal':
+      return `"${escapeRubyDQ(ir.value)}"`;

     case 'date_literal':
       return `Date.parse(${JSON.stringify(ir.value)})`;
@@ -408,7 +421,9 @@ function emitTypeExprParser(
         const errorMsg = c.label
           ? (c.label.includes(' ') ? c.label : `constraint '${c.label}' failed`)
           : 'constraint failed';
-        return `return p_fail(p, "${errorMsg}") unless (${conditionCode});`;
+        // Escape for safe embedding in a Ruby double-quoted string: user-controlled
+        // labels (e.g. `Int(i | 'any text': ...)`) must not trigger `#{...}` interpolation.
+        return `return p_fail(p, "${escapeRubyDQ(errorMsg)}") unless (${conditionCode});`;
       }).join(' ');

       return `->(v, p) { _r = (${baseParser}).call(v, p); return _r unless _r[:success]; ${varName} = _r[:value]; ${constraintChecks} _r }`;

Commit: d2a89a8

Release v1.0.1 containing the fix for CVE-2026-44266 / GHSA-7w38-ggh5-v542.

Exploit Details

  • GitHub Security Advisory: Official security advisory containing proof-of-concept Elo expressions demonstrating arbitrary command execution via string literals and subtype constraint labels.

Mitigation Strategies

  • Upgrade @enspirit/elo to version 1.0.1 or later to ensure '#' characters are properly escaped in generated Ruby string literals.
  • Invalidate and regenerate any cached or pre-compiled Ruby code produced by @enspirit/elo versions prior to 1.0.1.
  • Avoid using the Ruby compilation backend (-t ruby) for untrusted Elo expressions if immediate patching is not feasible; use the JavaScript, Python, or SQL backends instead.
  • Isolate execution of compiled expressions within restricted container sandboxes with dropped capabilities, read-only filesystems, and network egress controls.

Remediation Steps:

  1. Update package dependencies by running: npm install @enspirit/elo@^1.0.1
  2. Verify the installed version in package-lock.json or node_modules/@enspirit/elo/package.json matches 1.0.1 or higher.
  3. Purge any application caches storing previously compiled Ruby code strings generated from user-supplied Elo expressions.
  4. Audit CI/CD pipelines and local scripts for invocations of 'eloc -t ruby -x' against untrusted input files.

References

Read the full report for CVE-2026-44266 on our website for more details including interactive diagrams and full exploit analysis.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.