人気のJavaScript ライブラリ「expr-eval」にリモートコード実行の致命的な脆弱性(CVE-2025-12735)

セキュリティニュース

投稿日時: 更新日時:

人気のJavaScript ライブラリ「expr-eval」にリモートコード実行の致命的な脆弱性(CVE-2025-12735)

2025年11月8日 NPMで週80万超のダウンロードがある数式パーサ「expr-eval」に、細工した入力から任意コード実行(RCE)が可能になる致命的な脆弱性(CVE-2025-12735、CVSS 9.8)が見つかりました。CERT/CCは修正パッチを元リポジトリにプルリクエスト(PR #288)として提出していますが、現時点でマージは未定です。一方、アクティブにメンテナンスされているフォーク版 expr-eval-fork v3.0.0 で修正がリリースされています。利用している開発者は速やかな移行が推奨されます。

影響範囲

NPMでの週次ダウンロードは、約820,000(expr-eval)、約80,000(expr-eval-fork)となっており広く影響が及びます。

利用用途としてオンライン計算機、教育・シミュレーション、金融系ツール、NLP/AIでの数式解析など、ユーザー入力を評価する用途全般でリスクが高まります。

また入力式だけでなく、evaluate() に渡す変数オブジェクトが外部から影響を受ける実装は特に注意が必要です。

何が問題か

脆弱性は、Parser.evaluate() に渡される 変数/コンテキストオブジェクトの検証不備が原因です。攻撃者がここに関数オブジェクト等を紛れ込ませると、評価処理の過程でそれらが呼び出され、意図しないコード実行につながる可能性があります。

影響はオリジナルの expr-eval(最後の公開は6年前、v2.0.2系)と、そのフォークである expr-eval-fork の旧版に及びます。

修正状況(npm/GitHub)

  • expr-eval-fork v3.0.0:修正済みをリリース。

    • 評価可能な関数の許可リストを導入

    • カスタム関数は登録制に変更

    • 制約のテストカバレッジを拡充

    • 一部破壊的変更(Breaking Changes)が含まれます

  • expr-eval(オリジナル)

    • CERT/CCのPR #288 が提出済み(functions.jsへの制限、メンバーアクセス封じなどの変更)。

    • メンテナー不在によりマージ時期は未定です。

推奨アクション(すぐにできる対策)

まず、現行プロジェクトで expr-evalexpr-eval-fork がどこで使われているかを洗い出してください(例:npm ls expr-eval expr-eval-fork)。

依存関係が確認できたら、可能な環境では expr-eval-fork v3.0.0 へ移行し、ビルドと配布物を作り直します。

あわせて、Parser.evaluate() を呼んでいる箇所を総点検し、評価に渡すオブジェクトに関数や意図しないプロパティが紛れ込まないよう防御します。外部入力をそのままスコープに渡さず、必要なキーだけを取り出したプレーンな値に整形し、シリアライズ/ディープコピーでプロトタイプ連鎖を断つのが安全です。

評価時に使える関数は最小限に絞り、フォーク版の登録APIで明示的に許可する運用へ切り替えてください。

運用面では、npm audit やSCAツールをCIに組み込み、脆弱バージョンの混入をビルドで止める仕組みを入れ、依存のバージョン固定(lockfileの更新と監視)も併せて行います。以上を終えたら、変更範囲の単体テストを増やし、式評価に関わる入力境界と許可関数の想定外ケースを重点的に確認すると安全です。

参考:安全な利用の最小例

// expr-eval-fork v3 以降
import { Parser, registerFunction, allowOnly } from 'expr-eval-fork';

// 必要最小限の関数のみ許可(例:abs と pow)
allowOnly(['abs', 'pow']);

// どうしてもカスタム関数が必要な場合は明示登録
registerFunction('clamp', (x, min, max) => Math.min(Math.max(x, min), max));

// 変数オブジェクトはプリミティブのみを許可し、外部入力は検証する
const safeVars = Object.freeze({ x: 3, y: 4 });

const expr = new Parser().parse('pow(x,2) + clamp(y,0,10)');
console.log(expr.evaluate(safeVars)); // 9 + 4 = 13

互換性メモ

  • フォーク版v3では、ユーザー定義関数の扱いメンバーアクセスに制約が加わっています。既存コードは登録APIへの書き換えが必要になる場合があります。

  • ランタイムに関数をスコープへ無造作に注入していた実装は、動作しなくなる可能性があります。