
Co znajdziesz w tym artykule?
- 1 Wprowadzenie do problemu / definicja luki
- 2 W skrócie
- 3 Kontekst / historia / powiązania
- 4 Analiza techniczna / szczegóły luki
- 5 Praktyczne konsekwencje / ryzyko
- 6 Rekomendacje operacyjne / co zrobić teraz
- 7 Różnice / porównania z innymi przypadkami
- 8 Podsumowanie / kluczowe wnioski
- 9 Źródła / bibliografia
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) iexpr-eval-fork(fork). - Nasilenie: CVSS 9.8 (CISA ADP).
- Status poprawek: stabilna poprawka w
expr-eval-forkv3.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ą, że 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 nawet 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, że 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śli 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śli używacie pakietu, który pośrednio ciągnieexpr-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śli 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 kluczowe w wyrażeniach, jeżeli 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-evalproblem 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 / kluczowe wnioski
- CVE-2025-12735 to krytyczna luka w
expr-evalumożliwiająca RCE przez złośliwe funkcje w kontekścieevaluate(). - Najbezpieczniejsza ścieżka: migracja do
expr-eval-fork3.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-fork3.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)