High

expr-eval CVE-2025-12735 · CVE-2025-13204

Code execution and prototype pollution via unrestricted member access in expr-eval.

The problem

expr-eval <= 2.0.2 (all published versions) is affected by CVE-2025-12735, CVE-2025-13204 (CWE-94 Code Injection / CWE-1321 Prototype Pollution). The published package has no fix available — exactly what npm audit reports. `expr-eval` lets callers evaluate string expressions against a supplied scope, including member access such as `foo.bar`. Because member access was unrestricted, a crafted expression could reach JavaScript internals: `foo.__proto__` exposes (and can pollute) `Object.prototype`, and the `constructor` chain can reach the `Function` constructor to run arbitrary code. Any application that evaluates untrusted expressions is affected.

The fix — drop-in, no code changes

Add an overrides entry so every direct and transitive dependency on expr-eval resolves to the patched fork, then reinstall:

{
  "overrides": {
    "expr-eval": "npm:@keep-lts/expr-eval@^2.0.3"
  }
}

Equivalent for Yarn: use resolutions. The public API is unchanged — nothing else to do.

✓ Live on npm: @keep-lts/expr-eval  ·  or install directly: npm i @keep-lts/expr-eval

This is rarely the only one

If expr-eval turned up in your npm audit, there are very likely other abandoned dependencies in the same tree whose CVEs also have no fix on npm. Send us your npm audit output — or your Snyk / Dependabot list — and we'll tell you, for free, which of those findings we already fix. No call, no obligation.

Mid-audit and need a vendor on the hook? Keep LTS Pro adds an SLA on future CVEs and the SBOM / VEX artefacts your auditor will accept — all async, no calls.

What we changed

A `memberAccess(object, property)` guard wraps every runtime member-access site and throws when the property is `__proto__`, `constructor`, or `prototype`. Legitimate expressions — member access to ordinary properties, arithmetic, and built-in functions like `sqrt`/`max` — are unchanged. The same guard is present in `dist/bundle.js` (CommonJS), `dist/index.mjs` (ESM), and `dist/bundle.min.js` (regenerated from the patched source).

Proof of concept (the vulnerability)

const { Parser } = require('expr-eval');
const parser = new Parser();
parser.evaluate('foo.__proto__', { foo: {} }); // returns Object.prototype on the unpatched version
Patched version@keep-lts/expr-eval@2.0.3
Weekly downloads (affected pkg)505,077
Regression tests8 passing
LicenseMIT

How we keep it trustworthy

Full advisory and changelog ship inside the package (SECURITY.md, CHANGELOG.md).

← All maintained packages