Krytyczna luka w jsPDF (CVE-2025-68428): kradzież plików z serwera przez generowane PDF-y - Security Bez Tabu

Krytyczna luka w jsPDF (CVE-2025-68428): kradzież plików z serwera przez generowane PDF-y

Wprowadzenie do problemu / definicja luki

W bibliotece jsPDF wykryto krytyczną podatność typu Local File Inclusion / Path Traversal, oznaczoną jako CVE-2025-68428. Problem dotyczy wyłącznie buildów Node.js i pozwala atakującemu odczytywać dowolne pliki dostępne dla procesu Node, a następnie „przemycać” ich zawartość wygenerowanym PDF-em (czyli w legalnym artefakcie wyjściowym aplikacji).


W skrócie

  • Co jest podatne: jsPDF w wersjach < 4.0.0, tylko artefakty dist/jspdf.node.js i dist/jspdf.node.min.js.
  • Warunek ataku: użytkownik/atakujący musi mieć możliwość sterowania argumentem-ścieżką pliku przekazywanym do podatnych metod (bez twardego allowlistu/sanitizacji).
  • Skutek: wyciek tajnych danych (np. pliki konfiguracyjne, sekrety, klucze, pliki .env) do PDF, który aplikacja normalnie zwraca/zapisuje.
  • Poprawka: aktualizacja do jsPDF 4.0.0, gdzie domyślnie ograniczono dostęp do systemu plików i oparto egzekwowanie na Node.js Permission Model.

Kontekst / historia / powiązania

Podatność została zgłoszona w procesie GitHub Security Advisories (GHSA) i oceniona jako krytyczna (CNA score 9.2 w CVSS v4).
BleepingComputer zwraca uwagę, że ryzyko realnej eksploatacji zależy od tego, czy ścieżki plików są kontrolowane przez użytkownika, a także że w praktyce wdrożenie mitigacji przez Permission Model może wymagać nowszych wersji Node.


Analiza techniczna / szczegóły luki

Co dokładnie nie działa

Sednem problemu jest metoda loadFile w buildzie Node.js: jeśli atakujący kontroluje pierwszy argument (ścieżkę), biblioteka potrafi odczytać wskazany plik z dysku i dołączyć jego zawartość do PDF.

Metody podatne (wektory wejścia)

Oprócz loadFile, podatne są też metody, które pośrednio z niej korzystają:

  • addImage
  • html
  • addFont

Przykładowy wektor ataku (model)

Jeśli aplikacja pozwala użytkownikowi wskazać „obrazek” lub zasób do osadzenia w PDF (np. parametr imagePath), atakujący może zamiast tego podać ścieżkę do pliku z sekretami. Zawartość trafi do PDF „jakby nigdy nic”, a następnie wycieknie kanałem dystrybucji dokumentu (download, email, storage, S3 itp.).

Dlaczego poprawka jest „nietypowa”

W jsPDF 4.0.0 ograniczenie dostępu do systemu plików jest domyślne, a rekomendowana ochrona opiera się na Node.js Permission Model (uruchomienie procesu z flagą --permission i precyzyjnymi allowlistami zasobów).


Praktyczne konsekwencje / ryzyko

Największe ryzyko dotyczy usług, które:

  • generują PDF-y po stronie serwera (Node.js),
  • przyjmują od użytkownika parametry wpływające na to, jakie pliki/zasoby są osadzane (np. „logo”, „załącznik”, „szablon”, „font”, „HTML do renderu”),
  • działają z szerokimi uprawnieniami do systemu plików lub z dostępnymi sekretami na dysku (np. .env, klucze prywatne, konfiguracje).

Warto też zauważyć „cichy” charakter eksfiltracji: to nie musi być osobny kanał C2 – dane mogą wyciec w legalnym pliku PDF, który system i monitoring traktują jako normalny rezultat pracy aplikacji.


Rekomendacje operacyjne / co zrobić teraz

1) Aktualizacja zależności (priorytet)

  • Zaktualizuj do jspdf@4.0.0 (lub nowszej).

2) Wymuś Permission Model w Node.js (jeśli generujesz PDF-y na serwerze)

Uruchamiaj proces z ograniczeniami i minimalnym zakresem odczytu:

node --permission --allow-fs-read=/app/assets,/app/templates ./server.js

Flagi --allow-fs-read i --permission są elementem Permission Model (zwróć uwagę: zbyt szerokie reguły, np. --allow-fs-read=*, de facto kasują ochronę).

Uwaga operacyjna: te flagi dotyczą całego procesu Node, nie tylko jsPDF — mogą ujawnić ukryte zależności od dostępu do FS i wywołać regresje.

3) Jeśli nie możesz zaktualizować natychmiast

  • Wprowadź twardy allowlist (mapowanie identyfikator → bezpieczna ścieżka) zamiast przepuszczać ścieżki od użytkownika.
  • Zablokuj sekwencje path traversal (../, ..\\) i używaj normalizacji (path.resolve) + sprawdzania prefiksu katalogu bazowego.
  • Rozdziel role: osobny serwis do generowania PDF z minimalnymi uprawnieniami i bez sekretów na dysku.

4) Szybkie „triage” ekspozycji w kodzie

Szukaj wywołań:

  • addImage(...), html(...), addFont(...), loadFile(...)
    gdzie pierwszy argument może pochodzić z: request params, body, query string, upload metadata, bazy danych modyfikowalnej przez userów.

Różnice / porównania z innymi przypadkami

  • Klasyczne LFI/Path Traversal często kończy się odpowiedzią HTTP z treścią pliku lub błędem. Tutaj wyciek jest „opakowany” w PDF, który bywa logowany, archiwizowany i wysyłany dalej — co utrudnia wykrycie i zwiększa promień rażenia (retencja, kopie, systemy DLP).
  • Nietypowe jest też oparcie remediacji na mechanizmie runtime (Permission Model) zamiast wyłącznie na walidacji wejścia w bibliotece — co zwiększa znaczenie poprawnej konfiguracji środowiska uruchomieniowego.

Podsumowanie / kluczowe wnioski

  • CVE-2025-68428 to krytyczna podatność w jsPDF (Node build) umożliwiająca odczyt lokalnych plików i ich eksfiltrację przez generowane PDF-y.
  • Jeżeli w Twojej aplikacji użytkownik może wpływać na ścieżki/zasoby przekazywane do addImage/html/addFont/loadFile, traktuj temat jako pilny.
  • Najlepsza ścieżka: upgrade do 4.0.0 + uruchamianie Node z --permission i wąskimi allowlistami FS.

Źródła / bibliografia

  1. GitHub Security Advisory (jsPDF) – GHSA-f8cm-6447-x5h2 (GitHub)
  2. NVD (NIST) – CVE-2025-68428 (NVD)
  3. Endor Labs – analiza i rekomendacje dla CVE-2025-68428 (endorlabs.com)
  4. Node.js Documentation – Permission Model / flags --permission, --allow-fs-read (Node.js)
  5. BleepingComputer – kontekst i ryzyka wdrożeniowe mitigacji (BleepingComputer)