expr-eval Code Injection via toJSFunction (CVE-2026-12866, CVSS 9.8): Never Pass Untrusted Input, Move to expr-eval-fork
A critical code-injection flaw (CVE-2026-12866, CVSS 9.8) affects expr-eval, a JavaScript math-expression library with 800k+ weekly downloads used in AI and NLP apps. Its toJSFunction() compiles input via new Function(), so untrusted expressions run as code. Stop passing untrusted input and move to expr-eval-fork.

Makoto Horikawa
Backend Engineer / AWS / Django
A critical code-injection flaw (CVE-2026-12866, CVSS 9.8) affects expr-eval, a JavaScript math-expression library with 800k+ weekly downloads used in AI and NLP apps. Its toJSFunction() compiles input via new Function(), so untrusted expressions run as code. Stop passing untrusted input and move to expr-eval-fork.
A critical flaw has been reported in expr-eval, a widely used JavaScript component for evaluating math expressions, that lets an attacker run their own code simply by passing in a crafted string. The vulnerability is tracked as CVE-2026-12866, with a CVSS severity score of 9.8 out of 10 (the top "critical" band). Security firm Snyk published it on June 23, 2026.
expr-eval is a staple component with more than 800,000 weekly downloads, embedded in online calculators, education tools, financial apps, and even AI and natural-language-processing apps that read math out of prompts. The issue is not limited to one release: all versions are listed as affected, and many services carry this component without realizing it.
What expr-eval is, and why it is dangerous
expr-eval is a library (a software component) that takes a math expression as a string, like "1 + 2 * (3 - x)", and computes the answer. JavaScript has a built-in eval() that runs any string as code, but because it can execute anything it is dangerous, so libraries like expr-eval were chosen for the safer goal of "just doing math."
The problem lies in expr-eval's toJSFunction() API. To speed up repeated calculations, it compiles the expression into a real JavaScript function, and internally it uses new Function() β the same mechanism family as the dangerous eval(). In other words, a string received from a user can turn directly into "code that gets executed." According to the vulnerability database entry, an attacker can send a command disguised as a math expression, escape the calculation sandbox, and run arbitrary code with the application's privileges.
This component has actually seen a cluster of vulnerabilities around the same period. In late 2025, a separate entry point (the config passed to evaluate()) allowed remote code execution as CVE-2025-12735, and the US CERT/CC also issued an advisory (VU#263614). CVE-2026-12866 is easiest to understand as a sibling β "another door" into the same house.
Who targets this, and what they do
The people who abuse this hole are attackers going after web services and AI apps that process user-supplied math or formulas as raw strings. AI assistants that "pull a formula out of text and compute it," and business tools that let users write their own calculation rules, are increasingly common β and those input paths are exactly the target.
What the attacker does is simple. They type a command disguised as a formula into the math input field, aiming to run their own program on the server. The CVSS assessment notes that the attack needs no login and no special user interaction (anyone can try it over the network), so it can succeed the moment input reaches the attacker's control.
If it succeeds, the damage shows up for everyday users as theft of personal data or input, and account takeover, and for the company running the system as server takeover, a foothold into the internal network, and service outages. A tiny calculation component can become the front door to the whole service. As the axios incident β malware slipped into an npm package with 100 million weekly downloads β showed, the more popular a component is, the wider the blast radius.
Overview of this vulnerability
There is more than one expr-eval vulnerability, so let us avoid confusion. The newly published one is at the top of the table: CVE-2026-12866.
CVE-2026-12866: Code execution via toJSFunction()
When an attacker's string is passed to toJSFunction(), which converts an expression into a native JavaScript function, the content runs as code. CVSS is 9.8; the attack vector is network, no authentication, no user interaction. Snyk assigned the CVE, and the finder is credited as Dinh Tuan Doan.
| CVE | Entry point | Type | CVSS | Status |
|---|---|---|---|---|
| CVE-2026-12866 new | toJSFunction() | Code injection (CWE-94) | 9.8 Critical | All versions affected fix unconfirmed |
| CVE-2025-12735 | evaluate() config | Remote code exec | 9.8 Critical | Fixed in fork 3.0.0 |
| CVE-2025-13204 | Expression parsing | Prototype pollution | High | Addressed in fork |
What all three share is expr-eval's root design: it turns a user-written expression into something directly executable. The CVE-2025-12735 details point to the same structure.
A timeline of expr-eval's vulnerabilities
β swipe to move
What is confirmed, and what is still unclear
This vulnerability is a little different from a "simple bug," and some parts call for caution before drawing firm conclusions. Here is what can be confirmed from primary sources, separated from what is not yet settled.
β Confirmed facts
- βCVE-2026-12866 is CVSS 9.8 (Critical), assigned by Snyk and published June 23, 2026 (NVD)
- βtoJSFunction() compiles an expression into a native function via new Function(), so if an attacker controls the expression, arbitrary code runs (vulnerability database)
- βThe scope is listed as "all versions," and Snyk shows no fixed version across the package history (Snyk)
- βThe original (silentmatt) is unmaintained since a release ~6 years ago; maintenance has moved to expr-eval-fork (GitHub)
? Still unclear (unconfirmed)
- ?Whether a dedicated fix for CVE-2026-12866 itself will ship is unconfirmed. toJSFunction() is an API meant to "turn an expression into code," so β like eval() β it can be read as danger by design, and whether the vendor treats it as a vulnerability to fix or as "intended behavior" is not settled
- ?It is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog. No in-the-wild exploitation and no verifiable public PoC URL could be confirmed
- ?Whether the safeguards added in expr-eval-fork 3.0.0 also neutralize abuse via toJSFunction() needs case-by-case verification
The key point: this is not a simple "install the patch and you are done" situation. Just as you must never pass external input to eval(), the essential fix is reconsidering the usage itself β do not pass untrusted input to toJSFunction().
Check whether your service is affected
Even if you do not use expr-eval directly, another library often pulls it in (a transitive dependency). It tends to hide inside AI and NLP tooling especially, so first check whether your project uses it.
- Run
npm ls expr-eval expr-eval-forkto see if it is in your dependency tree - If it is, check whether your code passes strings that came from outside into
toJSFunction()orevaluate() - Forms and APIs that accept formula input, and the calculation features of AI assistants, are likely candidates
Use our OSS Supply Chain Scanner, which checks for known vulnerabilities like this just by pasting in your dependencies β npm or Python. For another library-borne vulnerability, the i18next case is a useful reference too.
What to do now
There are three pillars. The most important is cutting off the source of the input.
1. Do not pass untrusted input to toJSFunction() or evaluate(). Avoid designs that execute strings from users or over the network as math directly. If you truly must compute external expressions, validate input strictly and restrict it to allowed symbols and digits only. Treat toJSFunction() with the same danger level as eval().
2. Move off the unmaintained original to the successor, expr-eval-fork. The original expr-eval is no longer updated, and even the earlier CVE-2025-12735 is not adequately fixed on the original. The actively maintained expr-eval-fork at 3.0.0 and later ships defenses such as a safe-function allowlist. SC Media also recommends migrating.
3. Make dependency inventory a routine. "Popular but unmaintained" components like this one keep producing similar vulnerabilities if left alone. Techzine also urges checking your version and migrating. Knowing what is pulled in β transitive dependencies included β and reselecting components based on maintenance status is, in the end, the best defense.
Summary
CVE-2026-12866 is a critical, CVSS 9.8 problem in which passing external input to toJSFunction() in the staple math library expr-eval runs arbitrary code. But this is less a standalone bug than something rooted in the component's design β turning a user's expression into something directly executable β and it is continuous with the earlier CVE-2025-12735. Before waiting for a patch, first confirm whether you are passing untrusted input into this component, and move from the unmaintained original to the successor. A small calculation component can become the front door to your entire service, and is worth inspecting on that assumption.
Sources
- βΈNVD - CVE-2026-12866
- βΈCIRCL Vulnerability-Lookup - CVE-2026-12866
- βΈSnyk - expr-eval package vulnerabilities
- βΈBleepingComputer - Popular JavaScript library expr-eval vulnerable to RCE flaw
- βΈCERT/CC - VU#263614 expr-eval can lead to arbitrary code execution
- βΈSC Media - RCE possible with expr-eval JavaScript library vulnerability
- βΈTechzine - Critical vulnerability exposed in JavaScript library expr-eval
- βΈCVE Details - CVE-2025-12735
- βΈGitHub - silentmatt/expr-eval
- βΈnpm - expr-eval-fork