CVE-2026-12866 Overview
CVE-2026-12866 affects all versions of the expr-eval JavaScript package, a popular math expression parser used in Node.js applications. The vulnerability exists in the toJSFunction() API, which compiles user-supplied expressions into native JavaScript using the new Function() constructor. Attackers can craft expressions that escape the intended sandbox and execute arbitrary JavaScript within the host application's context. The flaw maps to CWE-94: Improper Control of Generation of Code.
Critical Impact
Remote attackers can achieve arbitrary code execution in any application that passes untrusted input to expr-eval's toJSFunction(), leading to full server compromise.
Affected Products
- expr-eval npm package — all versions
- Node.js applications that invoke toJSFunction() with attacker-influenced input
- Downstream packages and services bundling expr-eval as a dependency
Discovery Timeline
- 2026-06-23 - CVE-2026-12866 published to the National Vulnerability Database
- 2026-06-23 - Last updated in NVD database
Technical Details for CVE-2026-12866
Vulnerability Analysis
The expr-eval library markets itself as a safer alternative to eval() for evaluating math expressions. However, the toJSFunction() API breaks that assumption. Instead of interpreting expressions through the library's internal AST evaluator, this function concatenates the parsed expression into a string and passes it to new Function(). The resulting native function executes inside the calling process with full JavaScript privileges.
The expression sandbox does not enforce a safe character or token allow-list before code generation. Attackers can inject JavaScript constructs that survive the parser and reach the dynamic compilation step. Once new Function() runs the crafted payload, the attacker controls execution in the application's context.
Root Cause
The root cause is improper code generation [CWE-94]. The library transforms user-controlled expressions directly into executable JavaScript without isolating them from the host runtime. Use of new Function() on attacker-influenced strings collapses the intended boundary between data and code.
Attack Vector
The vulnerability is network-exploitable when an application exposes an HTTP endpoint, message handler, or API that forwards user input to toJSFunction(). No authentication or user interaction is required if the vulnerable endpoint is publicly reachable. Common exposure patterns include formula evaluators, reporting tools, calculator services, and rule engines that accept expressions from end users. The vulnerability mechanism and proof points are discussed in the GitHub Issue #292 Discussion and the Snyk advisory SNYK-JS-EXPREVAL-15054690.
No verified public proof-of-concept code is provided in the advisory. The exploitation pattern is documented in the expression evaluation source code, where the toJSFunction() implementation builds a string and invokes new Function() on it.
Detection Methods for CVE-2026-12866
Indicators of Compromise
- Unexpected child processes spawned by Node.js runtimes, such as sh, bash, cmd.exe, or powershell.exe
- Outbound connections from Node.js application servers to unfamiliar hosts shortly after expression-evaluation API calls
- Application logs showing unusually long, malformed, or syntactically suspicious expression payloads submitted to evaluator endpoints
- Filesystem writes or reads by Node.js processes outside of expected application directories
Detection Strategies
- Inventory all uses of expr-eval across application source and package-lock.json files, then identify every call site invoking toJSFunction()
- Add static analysis rules that flag any code path passing request-derived data into toJSFunction() or Parser.parse(...).toJSFunction()
- Inspect runtime telemetry for Node.js processes invoking child_process, fs, or network APIs immediately following expression-evaluation traffic
Monitoring Recommendations
- Forward Node.js application and process telemetry into a centralized analytics platform to correlate expression input with subsequent process or network activity
- Alert on new Function() invocations originating from request handlers in environments where dynamic compilation is unexpected
- Track dependency graphs for the expr-eval package and trigger alerts when a patched version becomes available upstream
How to Mitigate CVE-2026-12866
Immediate Actions Required
- Audit all application code for calls to toJSFunction() and remove them where untrusted input can reach the function
- Replace toJSFunction() with the library's interpreted evaluate() method, which does not invoke new Function()
- Apply strict input validation that rejects any expression containing identifiers, property accessors, or characters outside an arithmetic allow-list
- Treat the expr-eval dependency as deprecated for any use case involving user-controlled expressions and plan migration to a hardened expression evaluator
Patch Information
At the time of publication, no fixed version of expr-eval is listed in the advisory. Because all versions are affected, organizations must remove or replace the dependency, or eliminate use of toJSFunction() until an upstream patch is released. Track remediation status through the Snyk advisory SNYK-JS-EXPREVAL-15054690 and GitHub Issue #292 Discussion.
Workarounds
- Switch evaluation calls from parser.parse(expr).toJSFunction(vars) to parser.parse(expr).evaluate(scope) to avoid new Function() compilation
- Run expression evaluation inside an isolated worker or sandboxed VM context with no access to require, process, or filesystem APIs
- Enforce a server-side allow-list of permitted operators, function names, and variable identifiers before passing input to the parser
- Apply egress network controls on application hosts so that successful code execution cannot easily reach attacker infrastructure
# Configuration example: safer evaluation pattern
# Replace vulnerable toJSFunction() usage
# const fn = parser.parse(userInput).toJSFunction(['x']); // vulnerable
# const result = fn(value);
# With interpreted evaluation against a fixed scope
# const result = parser.parse(userInput).evaluate({ x: value });
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

