Disclosure: this page contains affiliate links. East Bay Cyber may earn a commission if you buy through them, at no extra cost to you. That never changes how we rank products. Editorial policy.
CVE-2026-12866: Critical expr-eval Code Execution
Critical CVSS (9.8) reachable over network.
TL;DR -
expr-evalthrough version2.0.2can enable arbitrary JavaScript execution throughtoJSFunction(). - Applications processing untrusted expressions, variables, formulas, or objects may be affected. - No patched version is currently listed, and a public proof of concept exists. - CISA KEV does not currently include CVE-2026-12866, but exposed deployments should be treated as urgent.
CVE-2026-12866 is a critical expr-eval vulnerability that can enable arbitrary JavaScript code execution when attacker-controlled data reaches Expression.prototype.toJSFunction(). The affected npm package versions include 2.0.2 and earlier, as well as corresponding WebJars artifacts.
Organizations should identify reachable toJSFunction() call paths, block untrusted input, investigate potentially exposed systems, and replace or isolate the dependency where practical. Teams reviewing this issue should also maintain an up-to-date incident response planning checklist for containment, evidence preservation, and recovery.
Are You Affected?
CVE-2026-12866 affects the npm package expr-eval through version 2.0.2. The same vulnerable code is also distributed through the WebJars package org.webjars.npm:expr-eval.
Risk arises when an application allows attacker-controlled expressions, variables, formula data, or objects to reach the Expression.prototype.toJSFunction() API.
| Field | Value |
|---|---|
| CVE ID | CVE-2026-12866 |
| Package | expr-eval |
| Affected npm versions | <= 2.0.2 |
| Affected WebJars versions | org.webjars.npm:expr-eval <= 2.0.2 |
| CVSS | 9.8 Critical |
| Attack vector | Network exposure is implied by the CVSS 9.8 assessment; the complete vector was not returned in the reviewed NVD response |
| Authentication required | Not independently confirmed because the complete CVSS vector was unavailable |
| Privileges required | Not independently confirmed because the complete CVSS vector was unavailable |
| Patch available | No patched version listed |
| Public PoC | Yes |
| Confirmed exploitation in the wild | Not established by the reviewed sources |
| CISA KEV | No, on_kev: false |
The package is not automatically exploitable merely because it is installed. Exposure depends on application behavior. Prioritize internet-facing services, APIs, administrative consoles, workflow engines, report builders, calculators, rule systems, and automation tools that accept expressions or formula-like input from users, tenants, integrations, or uploaded configuration.
Search both direct and transitive dependencies. A service may not import expr-eval in its own source tree but may receive it through a bundled frontend, a WebJars artifact, or another npm dependency. Treat any use of toJSFunction() with untrusted data as a high-risk path until reviewed.
Analyst’s Take: Package presence is only the starting point. The priority is determining whether attacker-controlled data can reach
toJSFunction(). Because no patched version is listed, exposed call paths need containment or removal rather than a routine dependency upgrade.
The Fix, If You’re in a Hurry
No upstream fixed version was identified in the reviewed advisory material. The explicit affected range is expr-eval <= 2.0.2, and the GitHub Advisory Database lists no patched version. There is no verified upgrade target that can be provided as a safe fixed-version command.
The immediate mitigation is to prevent untrusted expressions and values from reaching toJSFunction(). If the application does not need code generation, remove that call from request-processing paths and use a safer, non-code-generating evaluation approach only after reviewing its security properties.
If the functionality is required, replace expr-eval with a maintained alternative that does not compile attacker-influenced input into executable JavaScript. Until that change is complete:
- Disable public expression or formula features where possible.
- Reject or constrain untrusted expressions before parsing.
- Isolate the vulnerable processing component.
- Remove unnecessary filesystem, network, credential, and process-execution access.
- Review logs and rotate potentially exposed secrets.
- Rebuild and redeploy from trusted artifacts.
If you use VPN or endpoint-security tools as part of broader containment, evaluate providers such as NordVPN or Malwarebytes according to your organization’s security and privacy requirements. These tools do not remediate the vulnerable dependency itself.
Technical Notes
Identify installed versions and call sites before changing production behavior:
npm ls expr-eval
npm audit --json
grep -RIn --exclude-dir=node_modules \
-E 'toJSFunction[[:space:]]*\\(|expr-eval|new[[:space:]]+Function' .
For a WebJars deployment, inspect Maven dependencies:
mvn dependency:tree -Dincludes=org.webjars.npm:expr-eval
Do not treat a package-manager reinstall as remediation when no fixed version exists. Block or remove the vulnerable execution path, then rebuild and redeploy. If a temporary code change is possible, reject requests that invoke the affected feature and log the rejection for incident review.
Where processing cannot be removed, isolate it in a separate process or container with no unnecessary filesystem, network, credential, or process-execution access.
How This Vulnerability Works
The vulnerable behavior is associated with Expression.prototype.toJSFunction(). The API converts an expression into JavaScript source and compiles that source through the JavaScript Function constructor, commonly represented as new Function().
Input intended to remain within a mathematical or logical expression language can therefore influence code that executes in the application’s JavaScript runtime.
The issue is classified as CWE-94, Improper Control of Generation of Code. An application becomes exposed when it accepts attacker-controlled expressions or values and supplies them to the vulnerable API. The resulting function runs with the capabilities available to the host process rather than inside a complete security sandbox.
The published exploitation technique abuses value conversion during expression compilation. A crafted object can provide a custom toString() method. When the library converts the value while generating JavaScript, that method can execute Node.js operations. The documented proof of concept demonstrates filesystem access and command execution, including an attempt to run whoami.
A representative exploitation pattern is shown below. This is not a recommendation for testing against production systems; use only an isolated, disposable environment with authorization.
const { Parser } = require('expr-eval');
const parser = new Parser();
const expr = parser.parse('[cmd]');
const payload = {
toString: () => {
const fs = process.mainModule.require('fs');
const cp = process.mainModule.require('child_process');
fs.writeFileSync('expr-eval-poc.txt', 'PWNED');
return cp.execSync('whoami').toString().trim();
}
};
const fn = expr.toJSFunction('', { cmd: payload });
console.log(fn());
The exact post-exploitation impact depends on the Node.js process identity, container or host permissions, network access, secret injection, and available runtime APIs. Possible consequences include:
- Application-data theft
- Credential and environment-variable exposure
- Arbitrary file writes
- Child-process execution
- Lateral movement
- Full compromise of the service account
Severity, Explained
The reported CVSS base score is 9.8 Critical. That score indicates a vulnerability with potentially severe confidentiality, integrity, and availability consequences and a low-friction attack scenario.
It does not prove that every installation is remotely exploitable. Practical risk depends on whether an attacker can reach a code path that passes controlled data to toJSFunction().
The complete CVSS vector was not returned by the NVD response used for this assessment. Therefore, the exact values for attack vector, attack complexity, privileges required, user interaction, scope, and confidentiality, integrity, and availability impacts should not be reconstructed from the score alone. Authentication and privilege requirements are recorded here as unconfirmed rather than inferred.
Operationally, the important distinction is between package presence and reachable vulnerable functionality. A backend that uses expr-eval only with fixed, administrator-controlled formulas may have lower exposure than a public formula-builder API.
An application behind authentication can still be at serious risk if ordinary users, compromised accounts, tenants, or integrations can submit expressions.
Is It Being Exploited?
A public proof of concept exists. The Snyk advisory documents an exploitation pattern that uses toJSFunction() with a crafted object and demonstrates filesystem and command-execution behavior.
Public exploit material lowers the barrier to testing and adaptation, especially for attackers who can identify applications exposing expression-processing functionality.
Confirmed exploitation in the wild was not established by the reviewed sources. CISA’s Known Exploited Vulnerabilities catalog does not currently list CVE-2026-12866, and the assessment returned on_kev: false.
There is therefore no CISA KEV date-added entry, federal remediation deadline, required action, or ransomware-campaign flag for this CVE at the time of assessment.
CISA KEV status is not a clean bill of health. It reflects catalog status, not proof that exploitation is impossible or absent. Systems that allow attacker-controlled access to toJSFunction() remain high risk because the vulnerability provides a path to arbitrary JavaScript execution and public exploitation guidance is available.
Detecting It in Your Environment
Start with software inventory and source review. Search lockfiles, package manifests, build artifacts, container layers, and Maven dependency trees for both expr-eval and org.webjars.npm:expr-eval.
Confirm whether any installed version is 2.0.2 or earlier. Then locate toJSFunction() calls and trace the origin of every expression, variable, and object passed to them.
Runtime investigation should focus on evidence of unexpected code execution after expression-processing requests. Look for:
- Child-process creation
- Filesystem writes
- Unusual outbound connections
- Access to environment variables
- Access to application credentials
- Unexpected changes to temporary or application directories
Because exploitation may occur during expression compilation rather than normal function evaluation, telemetry should cover the process that parses or compiles expressions, not only the final endpoint response.
Technical Notes
Search application logs for expression-processing requests and suspicious command or file activity. The exact endpoint and field names vary, so use application-specific routes in addition to generic patterns:
grep -RInE \
'toJSFunction|expr-eval|expression|formula|rule|filter|whoami|child_process|process\\.mainModule|execSync|spawn|writeFile' \
/var/log /srv 2>/dev/null
A Linux audit rule can help identify child processes launched by a Node.js service. Replace the executable path and service identity for the target environment:
auditctl -a always,exit -F arch=b64 \
-S execve -F exe=/usr/bin/node \
-k node-child-process
Review matching events:
ausearch -k node-child-process -i
For an Elastic-style query, correlate the vulnerable service with process and file activity:
(process.parent.name : ("node" or "nodejs") and
process.name : ("sh" or "bash" or "whoami" or "curl" or "wget" or "python*" or "nc"))
or
(process.parent.name : ("node" or "nodejs") and
file.path : ("*/expr-eval-poc.txt" or "*/.ssh/*" or "*/etc/passwd"))
The filename expr-eval-poc.txt is only an example from the published demonstration and should not be treated as a required indicator. Attackers can change filenames, commands, and execution methods.
Stronger detection comes from correlating an expression endpoint request with a new child process, unexpected file write, credential access, or outbound network connection.
If untrusted input may have reached the vulnerable API, preserve logs and investigate before simply restarting the service. Review environment variables, recently accessed secrets, package-manager credentials, cloud metadata access, SSH material, application data, and outbound connections. Rotate exposed secrets after containment, and rebuild affected workloads from trusted artifacts.
For related defensive context, see why network segmentation matters for SMB security. Segmentation cannot fix the vulnerable code, but it can reduce the blast radius if a service is compromised.
Response Checklist
Use the following sequence for a suspected or confirmed exposure:
- Identify affected assets. Inventory npm, bundled frontend, container, and WebJars deployments.
- Find reachable call sites. Locate
toJSFunction()and trace all user-controlled inputs. - Contain the path. Disable public expression processing or block untrusted requests.
- Preserve evidence. Retain application, authentication, process, filesystem, and network logs.
- Inspect for execution. Look for child processes, file writes, outbound connections, and credential access.
- Rotate secrets. Replace credentials that may have been available to the affected process.
- Replace or isolate. Remove the dependency or run the feature in a tightly restricted environment.
- Validate remediation. Confirm that untrusted values cannot reach code-generating APIs.
- Monitor after recovery. Add detections for unexpected process, file, and network activity.
References and Further Reading
The NVD record identifies the vulnerable source area and tracks the CVE publication and modification history. The reviewed record reports CVE-2026-12866 as a critical issue affecting expr-eval, with NVD publication on 2026-06-23 and last modification on 2026-07-07.
Relevant references include:
- NVD source reference
- Upstream GitHub issue #292
- GitHub Advisory Database: GHSA-q9v2-7m5w-4693
- Snyk npm advisory: SNYK-JS-EXPREVAL-15054690
- Snyk WebJars advisory: SNYK-JAVA-ORGWEBJARSNPM-17662018
- Additional technical analysis from SentinelOne
The practical conclusion is straightforward: expr-eval versions through 2.0.2 should not receive attacker-controlled expressions or values through toJSFunction().
No fixed release is currently listed, so remediation requires disabling or removing the vulnerable path, replacing the dependency, or isolating the workload until a verified upstream fix becomes available.
This article may contain affiliate links. We earn a commission on qualifying purchases at no extra cost to you.