Popularna biblioteka JavaScript expr-eval z krytyczną luką RCE (CVE-2025-12735)

securitybeztabu.pl 1 dzień temu

Wprowadzenie do problemu / definicja luki

W bibliotece expr-eval (popularny parser i ewaluator wyrażeń matematycznych w JavaScript) ujawniono krytyczną podatność pozwalającą na zdalne wykonanie kodu (RCE) po przekazaniu złośliwego obiektu „kontekstu” do funkcji evaluate(). Problem został oznaczony jako CVE-2025-12735, a według oceny CISA (CVSS 3.1) ma wagę 9.8 – CRITICAL. Luka dotyczy zarówno oryginalnego pakietu expr-eval, jak i aktywnie utrzymywanego forka expr-eval-fork (naprawa dostępna od wersji 3.0.0).

W skrócie

  • Co: RCE poprzez złośliwe funkcje w obiekcie kontekstu przekazywanym do Parser.evaluate().
  • Zakres: expr-eval (oryginalny projekt) i expr-eval-fork (fork).
  • Nasilenie: CVSS 9.8 (CISA ADP).
  • Status poprawek: stabilna poprawka w expr-eval-fork v3.0.0; dla oryginalnego repo istnieje PR z łatą (#288), ale brak nowego wydania. Rekomendowana migracja do forka 3.0.0+.

Kontekst / historia / powiązania

expr-eval jest powszechnie używany w kalkulatorach webowych, narzędziach edukacyjnych, finansowych oraz – coraz częściej – w systemach NLP/AI, które parsują fragmenty matematyczne z tekstu. Oryginalne repozytorium jest rozwijane nieregularnie; społeczność utrzymuje forka expr-eval-fork, który wcześniej rozwiązywał inne kwestie bezpieczeństwa i utrzymania. CERT-CC i NVD odnotowują, iż biblioteka ma setki zależności pośrednich, co zwiększa zasięg oddziaływania podatności.

Analiza techniczna / szczegóły luki

Przyczyna: Funkcja evaluate() przyjmuje obiekt context (zbiór zmiennych i funkcji dostępnych w wyrażeniu). Brak prawidłowej walidacji/ograniczeń umożliwia przekazanie obiektów-funkcji, które parser następnie wywołuje w trakcie ewaluacji. To otwiera drogę do wykonywania niepożądanego kodu – w środowisku Node.js choćby do wywołań systemowych. NVD klasyfikuje problem jako skutkujący przejęciem poufności, integralności i dostępności (C:H/I:H/A:H).

Stan poprawek:

  • expr-eval-fork: wydanie 3.0.0 zawiera allowlist bezpiecznych funkcji, mechanizm rejestracji funkcji użytkownika i testy wymuszające ograniczenia.
  • expr-eval (oryginalne): istnieje Pull Request #288 od CERT-CC z analogiczną łatą; brak potwierdzanej publikacji nowej wersji w npm.

Identyfikatory i doradztwa: CVE-2025-12735, GHSA-jc85-fpwf-qm7x (GitHub Advisory).

Minimalny przykład zagrożonego wzorca (edukacyjnie, bez payloadu)

import { Parser } from 'expr-eval'; // Niebezpieczne: bezkrytyczne przekazywanie "context" z funkcjami od użytkownika const parser = new Parser(); const expr = parser.parse('customFn(x) + y'); // "context" pochodzi np. z wejścia użytkownika (to błąd!) const unsafeContext = { x: 2, y: 3, // użytkownik może wstrzyknąć dowolną funkcję customFn: (n) => n * 10, }; console.log(expr.evaluate(unsafeContext));

Wniosek: Sam fakt, iż funkcje z kontekstu są wywoływane, stanowi wektor wykonania kodu. W Node.js zamiast nieszkodliwego n * 10 atakujący może próbować odwołań do zasobów środowiska. Naprawa polega na odrzuceniu funkcji z kontekstu, whitelisting i jawnej rejestracji dopuszczalnych funkcji.

Praktyczne konsekwencje / ryzyko

  • Aplikacje serwerowe (Node.js): ryzyko RCE i dostępu do zasobów hosta, w tym plików, poświadczeń czy usług sieciowych. CVSS 9.8 od CISA odzwierciedla pełen kompromis (C/I/A = H).
  • Front-end (przeglądarka): brak bezpośredniego dostępu do systemu, ale możliwość nadużyć (kradzież tokenów, interakcje z API w kontekście użytkownika).
  • Łańcuch dostaw: biblioteka jest zależnością pośrednią w wielu projektach — podatność może „dotrzeć” do Was nawet, jeżeli nie importujecie jej wprost.

Rekomendacje operacyjne / co zrobić teraz

1) Szybka weryfikacja zależności

  • SBOM/grep: # npm npm ls expr-eval expr-eval-fork || true # pnpm pnpm ls expr-eval expr-eval-fork || true # yarn yarn why expr-eval || true
  • Skan doradztw: sprawdź GHSA i CVE w pipeline (np. npm audit, GitHub Dependabot).

2) Aktualizacja i pinning

  • Preferowany wariant: natychmiast **migruj do expr-eval-fork ≥ 3.0.0. npm i expr-eval-fork@^3.0.0 # lub w package.json ustaw: # "overrides": { "expr-eval": "npm:expr-eval-fork@^3.0.0" } jeżeli używacie pakietu, który pośrednio ciągnie expr-eval, rozważcie overrides/resolutions albo zgłoście issue do maintenera.
  • Oryginalny expr-eval: dopóki nie ma wydania z łatą, nie polegajcie na tym pakiecie w kontekście niezaufanego wejścia. PR #288 istnieje, ale brak gwarancji release’u.

3) Dodatkowe twarde zabezpieczenia (defense-in-depth)

  • Blokada funkcji w kontekście: nie przekazuj żadnych funkcji z danych użytkownika; jeżeli musisz, stosuj allowlistę i własną fabrykę funkcji.
  • Sandboxing: w Node.js rozważ izolację ewaluacji (np. oddzielny proces/VM, worker_threads, ograniczone uprawnienia).
  • WAF / filtrowanie: ogranicz długość, znaki i słowa najważniejsze w wyrażeniach, o ile użytkownicy dostarczają stringi do ewaluacji.
  • Logowanie i detekcja anomalii: monitoruj nietypowe wyrażenia i błędy parsera.

4) Testy regresyjne – przykład „bezpiecznego” wzorca po aktualizacji

import { Parser } from 'expr-eval-fork'; // jawna rejestracja dopuszczalnych funkcji const allowed = { abs: Math.abs, ceil: Math.ceil, floor: Math.floor, // ...lista minimalna, bez funkcji dostępowych }; const parser = new Parser({ functions: allowed }); // Do wyrażenia przekazujemy wyłącznie PRYMITYWY (liczby/napisy/boole) // i ewentualnie nazwy dopuszczonych funkcji; brak dowolnych obiektów-funkcji const expr = parser.parse('abs(x) + ceil(y)'); const safeContext = { x: -3.14, y: 2.2 }; console.log(expr.evaluate(safeContext)); // 6

5) Działania w CI/CD

  • Wymuś fail build przy wykryciu expr-eval < bezpiecznych wersji (policy as code).
  • Dodaj overrides/resolutions w monorepo i lockfile maintenance.
  • Publikuj nową wersję swoich bibliotek, aby konsumenci dostali zależność z poprawką (tzw. republish chain).

Różnice / porównania z innymi przypadkami

  • Analogiczne klasy błędów: CWE-94 („Improper Control of Code Generation”) – sytuacje, gdy system pozwala na wstrzyknięcie kodu poprzez „rozszerzalne” mechanizmy (np. eval-like, dynamiczne funkcje, konteksty). W expr-eval problem był subtelny, bo dotyczył wywoływania funkcji z kontekstu, a nie tylko parsowania tekstu. (Por. wpisy doradcze GHSA/NVD.)
  • Różnica do klasycznych XSS/RCE: tu łańcuch dostaw oraz biblioteka „bezpieczna zamiast eval” paradoksalnie stała się wektorem RCE przy niewłaściwej walidacji/konfiguracji.

Podsumowanie / najważniejsze wnioski

  • CVE-2025-12735 to krytyczna luka w expr-eval umożliwiająca RCE przez złośliwe funkcje w kontekście evaluate().
  • Najbezpieczniejsza ścieżka: migracja do expr-eval-fork 3.0.0+, pinning i republish bibliotek zależnych.
  • Nawet po aktualizacji stosuj zasadę najmniejszego zaufania wobec wejścia użytkownika i allowlistę funkcji.
  • Zweryfikuj łańcuch zależności – podatność często wchodzi pośrednio.

Źródła / bibliografia

  • BleepingComputer: pierwsze doniesienia, status patchy i rekomendacja migracji do expr-eval-fork 3.0.0. (BleepingComputer)
  • NVD (CVE-2025-12735) – opis, metryki, referencje, CVSS 9.8 wg CISA-ADP. (NVD)
  • CERT-CC Vulnerability Note VU#263614 – opis techniczny, wpływ na projekty AI/NLP, zalecenia. (kb.cert.org)
  • GitHub PR #288 (silentmatt/expr-eval) – propozycja łaty od CERT-CC, status w oryginalnym repo. (GitHub)
  • GitHub Advisory (GHSA-jc85-fpwf-qm7x) – doradztwo bezpieczeństwa. (GitHub)
Idź do oryginalnego materiału