TL;DR: CVE-2026-12866 shows that expr-eval’s toJSFunction() API can turn untrusted formulas or variables into executable JavaScript inside Node.js, creating remote code execution risk in apps that treat expression builders, scoring logic, or workflow rules as data, according to Corgea. The boundary failure is architectural, not a simple patch-level issue: if attacker input reaches source generation, the application has already crossed into code execution territory.
At a glance
What this is: CVE-2026-12866 is a remote code execution flaw in the npm package expr-eval where toJSFunction() can convert attacker-influenced expressions or variables into executable JavaScript.
Why it matters: It matters because formula engines often sit inside internal tools, scoring systems, and automation backends where a single trust-boundary mistake can expose secrets, privileged access, and production systems.
By the numbers:
- When AWS credentials are exposed publicly, attackers attempt access within an average of 17 minutes, and as quickly as 9 minutes in some cases.
👉 Read Corgea's analysis of CVE-2026-12866 in expr-eval
Context
CVE-2026-12866 is a code execution problem, but the broader governance issue is trust boundary collapse in application logic. expr-eval is often embedded in places teams no longer think of as code execution surfaces, such as pricing rules, scorecards, workflow conditions, and internal automation tools, which makes untrusted input especially dangerous when it reaches formula compilation.
For identity and access teams, the key concern is not the formula syntax itself but the runtime privileges available when the formula executes. If a Node.js process can reach secrets, tokens, cloud metadata, or deployment credentials, then a user-controlled expression engine becomes an NHI and secrets exposure problem as much as an application security issue. The pattern is common in systems that optimise for flexibility before they define execution boundaries.
Key questions
Q: What breaks when untrusted formulas reach toJSFunction() in Node.js apps?
A: The boundary breaks when expression data is converted into executable JavaScript inside the application process. At that point, a formula is no longer just business logic. If an attacker can influence the expression or the variables used during simplification, the runtime can execute code with the same privileges as the Node.js service.
Q: Why do formula engines create hidden NHI and secrets risk?
A: Because the application process usually runs with non-human identity privileges such as cloud tokens, database access, or deployment credentials. If dynamic formula compilation is unsafe, compromise of that process exposes whatever the service account can reach. The risk is not just code execution. It is credential abuse and blast-radius expansion.
Q: What do teams get wrong about expression evaluation security?
A: They often assume the parser is the main control point and overlook the code-generation step. In reality, the dangerous moment is when a library turns evaluated content into source code and feeds it to the runtime compiler. That optimisation changes the trust model and should be reviewed like any other execution boundary.
Q: How should security teams respond if attacker-controlled formulas were compiled already?
A: Treat the host as compromised at the application layer and investigate the process as if it executed attacker code. Rotate reachable secrets, check logs for formula changes and unusual payloads, and assess outbound network activity from the affected service. Re-enable execution only after the dangerous API path is removed or isolated.
Technical breakdown
Why toJSFunction() crosses the code execution boundary
toJSFunction() does not merely compute a value from an expression. It simplifies the expression, converts the result into JavaScript source text, and passes that text to new Function(), which compiles it inside the running Node.js process. That means the trusted boundary is not the parser alone, but the entire path from input to source generation. Once an attacker can influence the expression or variable objects used during simplification, the result is no longer data handling. It is runtime code creation with the application’s own privileges.
Practical implication: remove toJSFunction() from any path where expressions or variables can be influenced by users, tenants, or stored content.
How attacker-controlled variables become executable JavaScript
The dangerous part of this flaw is that the API can fold variable values into the token stream before generation. If those values are objects with custom stringification behaviour, they can shape the generated source in ways the developer did not intend. This is why a formula that looks mathematical can still become a code execution primitive. The risk is highest when applications accept saved formulas, config-driven rules, or multi-step workflows that replay expressions later against privileged runtime state.
Practical implication: restrict expression variables to primitive types and treat any object input as unsafe for formula compilation.
Why server-side Node.js usage is the highest risk
Browser-only usage is less dangerous because the strongest public proof of concept depends on Node-specific globals and built-in module access. Server-side Node.js applications, by contrast, commonly run with cloud credentials, database access, internal network reachability, and deployment tokens in the same process environment. That turns the formula engine into a powerful execution bridge. A successful exploit does not need to break the sandbox if the application itself already holds high-value secrets and ambient privilege.
Practical implication: separate formula execution from the primary application process and assume any compromise of that process exposes its reachable secrets.
Threat narrative
Attacker objective: The attacker wants code execution inside the Node.js process so they can steal secrets, run commands, and pivot into connected infrastructure.
- Entry occurs when an attacker supplies a crafted expression or variable object to a feature that accepts user-defined formulas, scoring logic, or workflow rules.
- Escalation happens when toJSFunction() simplifies attacker-influenced input and emits JavaScript source that new Function() compiles in the Node.js runtime.
- Impact follows when the resulting code executes with the application process’s privileges, allowing secret theft, shell command execution, or further compromise of connected systems.
Breaches seen in the wild
- Gladinet Hard-Coded Keys RCE Exploitation — Actively exploited hard-coded keys in Gladinet CentreStack and Triofox enable remote code execution.
- MITRE ATT&CK Enterprise Matrix — MITRE ATT&CK Enterprise — adversary tactics and techniques, threat detection, attack chain mapping, credential access, lateral movement, privilege escalation.
Read our 52 NHI Breaches Analysis report for a comprehensive view of breaches impacting Non-Human Identities including AI Agents.
NHI Mgmt Group analysis
Formula engines are part of the application code-execution surface, not just a convenience layer. When a library like expr-eval converts expressions into JavaScript source, the security model changes from safe evaluation to source generation. That is a materially different control problem because the application is now compiling data into code at runtime. Practitioners should classify these paths alongside other execution boundaries, not alongside ordinary input handling.
Untrusted variables are as dangerous as untrusted expressions. This CVE shows that the attack surface is not limited to the visible formula string. Any object that influences simplification or stringification can shape the generated function body, which means governance must cover every data path that reaches formula compilation. The practical conclusion is that the trust decision belongs before compilation, not after parsing.
Secrets exposure is the real blast-radius multiplier in formula execution bugs. A Node.js process with cloud tokens, database credentials, or deployment access turns a local RCE into a credential compromise problem. In identity terms, the application process is effectively a non-human identity with standing privilege, so its runtime boundaries matter as much as its source code. The safest design is least privilege for the process itself, not just for the users who trigger the formula.
Dynamic business logic needs explicit lifecycle governance. Teams often store formulas, rules, and scoring expressions as if they were configuration, then replay them later as if they were harmless data. That assumption fails when the expression engine can emit executable source. The category needs review, versioning, and approval controls that treat saved expressions as governed executable content, not as opaque business metadata.
Source-to-code conversion is the named failure mode here. The specific governance gap is allowing attacker-controlled input to cross a source-to-code conversion boundary without isolation. That failure mode is broader than expr-eval and will recur wherever optimisation logic uses runtime compilation. Practitioners should look for the same pattern anywhere an interpreter, template engine, or rules engine can emit executable code from untrusted input.
From our research:
- The average estimated time to remediate a leaked secret is 27 days, despite 75% of organisations expressing strong confidence in their secrets management capabilities, according to The State of Secrets in AppSec.
- Only 44% of developers are reported to follow security best practices for secrets management, exposing a significant developer behaviour gap.
- From our research: When AWS credentials are exposed publicly, attackers attempt access within an average of 17 minutes, and as quickly as 9 minutes in some cases, according to LLMjacking: How Attackers Hijack AI Using Compromised NHIs.
What this signals
Dynamic formula execution is becoming a governance problem wherever application teams treat stored business logic as harmless configuration. The immediate signal for practitioners is to inventory every place where user-defined expressions can be compiled, especially in internal tools and workflow engines. Where those paths exist, control ownership should sit with both application security and identity teams because the runtime often carries standing non-human identity privilege.
Source-to-code conversion debt: teams accumulate this debt when they optimise for reusability and performance before they define whether the input may ever become executable. That pattern will keep surfacing in template engines, rules engines, and low-code builders. The practical response is to classify compilation helpers as privileged components and link them to hard isolation requirements, not just secure coding guidance.
For practitioners
- Remove toJSFunction() from untrusted paths Eliminate any code path where user input, tenant input, or stored formulas reach Expression.prototype.toJSFunction(). If the feature is required, move it behind a privileged-only workflow and review every caller that can influence the expression or variables object.
- Treat formula variables as a data validation boundary Restrict variables passed into expression compilation to primitive values only, and reject objects, functions, and prototype-bearing payloads. Review HTTP inputs, database-stored formulas, config files, and plugin data as potential sources of source-code influence.
- Isolate formula execution from production secrets Run dynamic expression evaluation in a dedicated worker with no ambient cloud credentials, no signing keys, and tightly limited filesystem and network access. If the worker is compromised, the application process should not expose the same non-human identity privileges.
- Search for dangerous runtime compilation patterns Scan for new Function(), eval(), template-to-code flows, and any use of expr-eval in internal tools, workflow engines, or CI helpers. Prioritise paths where formulas are stored once and executed repeatedly against privileged data.
- Audit exposed secrets after any confirmed use of the API If attacker-controlled input reached toJSFunction(), rotate any secrets reachable from the process, review outbound connections, and inspect logs for unusual expression payloads or formula edits. Treat the host as having executed attacker code.
Key takeaways
- CVE-2026-12866 shows that a formula engine can become a code execution boundary once it turns untrusted input into JavaScript source.
- The main exposure is not just RCE, but the secrets and standing privilege held by the Node.js process that executes the formula.
- Teams should remove dangerous runtime compilation paths, isolate execution, and review any stored expression workflow as governed executable content.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
MITRE ATT&CK address the attack and risk surface, while NIST CSF 2.0, NIST SP 800-53 Rev 5 and CIS Controls v8 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| MITRE ATT&CK | TA0002 , Execution; TA0006 , Credential Access | Runtime compilation enables code execution and can expose credentials in the same process. |
| NIST CSF 2.0 | PR.AC-4 | The flaw turns application runtime trust into an access-control problem for privileged services. |
| NIST SP 800-53 Rev 5 | IA-5 | Secrets reachable from the Node.js process become high-value targets after code execution. |
| CIS Controls v8 | CIS-5 , Account Management | Shared service accounts and overly broad process identities magnify the impact of RCE. |
Map unsafe formula compilation to execution and credential-access tactics, then isolate or remove the path.
Key terms
- Source-to-Code Conversion: A security-sensitive transformation where application input is turned into executable source text and compiled at runtime. The risk is not the presence of a parser, but the moment untrusted data becomes code under the privileges of the running process.
- Formula Engine RCE: A remote code execution condition that appears in systems allowing user-defined expressions, rules, or scoring logic. It occurs when the engine generates executable code from input that should have remained data, often exposing secrets and internal network access.
- Privileged non-human identity: A privileged non-human identity is any service account, API key, token, certificate, workload, or AI agent that can reach sensitive systems and perform high-impact actions. The risk comes from the access it carries, not from whether a person is operating it directly. Governance must cover lifecycle, scope, and attribution.
- Execution boundary: The point at which an authorised task turns into a real system change, such as writing data, deleting records, spending money, or invoking a downstream tool. In AI governance, controlling the execution boundary matters more than simply approving access, because harm occurs when actions are allowed to complete unchecked.
What's in the full analysis
Corgea's full analysis covers the operational detail this post intentionally leaves for the source:
- The full exploit path showing how attacker-controlled input reaches new Function() through toJSFunction().
- The code-level proof of concept and payload patterns used to validate the runtime boundary failure.
- The dependency triage steps for finding expr-eval in package manifests and application call sites.
- The remediation guidance for isolating formula execution when no upstream fixed release is available.
Deepen your knowledge
The NHI Foundation Level course, the industry's only accredited NHI security programme, covers NHI governance, machine identity security, and secrets management. It is designed for practitioners who need to connect runtime privilege, access boundaries, and identity control across their programmes.
Published by the NHIMG editorial team on August 20, 2026.
NHI Mgmt Group — the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org