On this page (7 sections)

A critical vulnerability, tracked as CVE-2026-44267, affects Elo, a purely functional expression language built for no-code tools. A plain text string passed to Elo's JavaScript compiler can be turned into code that runs in the host runtime, which means arbitrary code execution on a Node.js server or in a visitor's browser.

If your application, build pipeline or internal tool uses the npm package @enspirit/elo to evaluate rules, configuration or form definitions that anyone other than you can influence, you should check your version now. The fix is in version 1.0.1.

What happened

A GitHub security advisory for the enspirit/elo repository was published on October 30, 2026 and updated on November 3, 2026. According to the GitHub advisory, an unauthenticated attacker who controls a string passed to any Elo JavaScript-emission path can run arbitrary code in the host JavaScript runtime.

The advisory says the flaw escapes any sandbox assumption around Elo being a safe data or DSL language, so integrators who assumed untrusted expressions could not do harm should revisit that. So far the advisory is the only source in our research, so the details below come from the advisory itself.

Technical details

The weakness is a classic sandbox escape, tracked with weakness identifiers CWE-79, CWE-94, CWE-693 and CWE-1336 in the CVE record. In JavaScript, almost every object exposes a property called constructor, and the constructor of a constructor is the built-in Function object, which can turn a string into running code. A safe expression language has to refuse access to such meta-properties. Elo did not.

The advisory points to three interacting parts of the source code:

  • The member access handler in src/transform.ts allows property access on values of type any, object or array without filtering the property name. This was the one place a denylist could have been added.
  • The JavaScript emitter in src/compilers/javascript.ts writes the property name verbatim into the generated code.
  • The parser in src/parser.ts accepts constructor as an ordinary identifier, so it passes type checking without any warning.

Combined, an expression that chains two constructor accesses compiles into a live call to the JavaScript Function object, and it then runs in the realm of whatever executes the compiled output. The advisory notes this is distinct from an earlier, medium-severity issue that required an attacker-controlled AST object; this one needs only a plain string, which is a weaker attacker requirement.

Who is affected

The advisory lists three entry points that share the same root cause and are fixed by the same patch:

Attack surfaces named in the advisory
Entry pointRealistic impact
Library API, defaultFormats.elo.parse()Code execution in Node.js for any application using Elo as a rule engine, configuration language or form-builder language
bin/elo command line toolCode execution on CI and DevOps hosts, including through the -f elo flag that feeds user-supplied files in as data
Browser playground at elo-lang.org/tryScript execution in the visitor's session on elo-lang.org when a crafted link with auto-run is opened

The CVSS vector in the advisory is network, low complexity, no privileges and no user interaction. In practice your exposure depends on whether untrusted text can reach Elo. A tool that only compiles Elo files written by your own team is far less exposed than a SaaS form builder that lets customers type expressions. Even so, a CI job that processes files from pull requests or third parties deserves attention.

How to check if you are exposed

Start by finding out whether the package is in your dependency tree, directly or indirectly. This read-only command lists every installed copy of the package; run it from the root of each project.

List installed versions of @enspirit/elo, including nested dependencies (run in the project…Shell
npm ls @enspirit/elo

Any version reported as 1.0.0 or lower is vulnerable. You can also search lockfiles, which is useful across many projects. This read-only command prints every lockfile line that mentions the package; run it from a directory holding your repositories.

Search lockfiles for the package name (run from a directory holding your repositories)Shell
grep -rn "@enspirit/elo" --include=package-lock.json --include=yarn.lock --include=pnpm-lock.yaml .

Note that the advisory's own proof of concept installs the package as elo; if you see a package under that name, confirm what it is and which version it resolves to before assuming it is unaffected. Also review where your code calls defaultFormats.elo.parse() or runs the bin/elo tool, and trace whether any input comes from users, uploaded files or external repositories.

What to do now

Caution. Updating a dependency can change behavior. Test the upgrade in a staging environment or CI run before deploying to production.

This command installs the fixed release and then lists the installed versions so you can confirm that 1.0.1 is the one reported. Run it in the project directory.

Upgrade to the fixed release and confirm the result (run in the project directory)Shell
npm install @enspirit/elo@1.0.1
npm ls @enspirit/elo
Tip. As defense in depth, treat any expression language as untrusted-input parsing. Run it in a separate low-privilege process or container, so a future escape does not hand over your application's secrets.

Detection and monitoring

The research does not report any exploitation in the wild, but a public proof of concept exists in the advisory, so assume attempts are possible. Look in application logs and stored rules or form definitions for the string constructor.constructor, which has no legitimate reason to appear in normal Elo expressions. This read-only search prints matching lines; adjust the paths to your own log and data locations.

Search a log or data directory for the suspicious property chain (read-only; adjust the path)Shell
grep -rn "constructor.constructor" /var/log/ /path/to/your/elo/data 2>/dev/null

On CI hosts, watch for unexpected shell or child process activity during jobs that run the Elo CLI. For internet-facing applications, a website firewall can add a layer of filtering for suspicious input, but it is not a substitute for upgrading. Our guide on checking whether a website is hacked covers what to look for if you suspect compromise, and Webforta Monitor can alert you to unexpected changes in the headers and certificates of your sites.

Timeline

  • October 30, 2026: advisory GHSA-33r5-xmm8-v6x5 published to the enspirit/elo repository.
  • November 3, 2026: advisory published to the GitHub Advisory Database and reviewed; the CVE data lists CVE-2026-44267 as published on this date, with a CVSS score of 9.8 as shown in the advisory.
  • Fix: version 1.0.1, with changes referenced in the repository commits, for example this commit.

Sources

This article is based on the public sources below. Details can change as vendors and researchers publish more; check the original advisories before acting on version numbers.

  1. CVE-2026-44267 - GitHub Advisory Databasegithub.com
  • CVE-2026-44267
  • npm
  • Node.js
  • code injection
  • supply chain