Krytyczna luka w @adonisjs/bodyparser (CVE-2026-21440, CVSS 9.2): path traversal umożliwia dowolny zapis plików na serwerze - Security Bez Tabu

Krytyczna luka w @adonisjs/bodyparser (CVE-2026-21440, CVSS 9.2): path traversal umożliwia dowolny zapis plików na serwerze

Wprowadzenie do problemu / definicja luki

Na początku stycznia 2026 ujawniono krytyczną podatność w ekosystemie AdonisJS, dotyczącą pakietu npm @adonisjs/bodyparser. Luka została zarejestrowana jako CVE-2026-21440 i oceniona przez CNA (GitHub) na CVSS 4.0: 9.2 (Critical).

To klasyczny przypadek path traversal (CWE-22) w mechanizmie obsługi uploadu multipart/form-data, który w określonych warunkach umożliwia zdalnemu atakującemu zapis plików w dowolnej lokalizacji w systemie plików serwera (a w konsekwencji — czasem także eskalację do RCE).

W skrócie

  • Co jest podatne: @adonisjs/bodyparser (mechanizm MultipartFile.move(...)).
  • Wektor ataku: upload przez endpoint, który przyjmuje multipart/form-data.
  • Sedno problemu: domyślne użycie niesanitowanej nazwy pliku pochodzącej od klienta oraz ryzykowne domyślne ustawienia w move() (m.in. domyślne nadpisywanie).
  • Skutek: arbitrary file write (dowolny zapis/nadpisanie pliku); potencjalnie RCE, jeśli uda się nadpisać pliki ładowane/wykonywane przez aplikację.
  • Naprawa: aktualizacja do @adonisjs/bodyparser 10.1.2 (stable) lub 11.0.0-next.6 (pre-release).

Kontekst / historia / powiązania

Informacja o luce pojawiła się publicznie w formie GitHub Security Advisory opublikowanego 2 stycznia 2026, a następnie została szerzej opisana m.in. w mediach branżowych 6 stycznia 2026.

Istotny kontekst z perspektywy ryzyka: advisory wskazuje, że dokumentacja pokazywała wcześniej przykłady prowadzące do użycia podatnej ścieżki (czyli „secure-by-default” nie zadziałało, a dodatkowo wzorce z docs mogły utrwalić ryzykowną praktykę).

Analiza techniczna / szczegóły luki

Gdzie jest błąd?

AdonisJS parsuje multipart/form-data przez BodyParser i udostępnia uploady jako obiekty MultipartFile. Problem dotyczy zachowania metody:

  • MultipartFile.move(location, options)

Jeżeli aplikacja wywołuje move() bez przekazania options.name, framework (w podatnych wersjach) domyślnie podstawiał nazwę pliku przesłaną przez klienta (client filename) i budował ścieżkę docelową w stylu path.join(location, name). Przy odpowiednio spreparowanej nazwie (np. z sekwencjami ../) atakujący może „wyjść” poza katalog uploadu i wskazać inną lokalizację zapisu.

Dodatkowo advisory podkreśla drugi element ryzyka: jeśli options.overwrite nie jest przekazane, domyślnie ustawione było na true, co ułatwia nadpisywanie istniejących plików.

Kiedy to działa w praktyce?

Wprost: potrzebny jest osiągalny endpoint uploadu, który:

  • przyjmuje multipart/form-data, oraz
  • używa MultipartFile.move() w sposób podatny (bez options lub bez sanitacji nazwy pliku).

Co zmienia poprawka?

W wydaniu 10.1.2 (analogicznie w 11.0.0-next.6) wprowadzono zmianę: MultipartFile.move(location) nie używa już domyślnie nazwy pliku od klienta. Zamiast tego generowana jest losowa, unikalna nazwa oparta o uuid. To jest świadomie opisane jako breaking change, ale dostarczone w patchu, aby szybko „zamknąć” klasę ataków wynikającą z niebezpiecznego domyślnego zachowania.

Praktyczne konsekwencje / ryzyko

Najbardziej bezpośrednim skutkiem jest arbitrary file write: atakujący może doprowadzić do zapisu pliku w ścieżce, której programista nie przewidział — łącznie z nadpisaniem krytycznych plików, jeżeli proces ma odpowiednie uprawnienia.

RCE nie jest „gwarantowane”, ale scenariusz jest realistyczny, jeśli możliwe jest nadpisanie:

  • kodu aplikacji,
  • skryptów uruchomieniowych,
  • konfiguracji ładowanej w runtime,
  • plików, które zostaną później wykonane lub zinterpretowane przez aplikację/środowisko.

W praktyce poziom ryzyka zależy od:

  • topologii wdrożenia (kontenery vs VM vs bare metal),
  • praw dostępu użytkownika systemowego uruchamiającego node,
  • tego, gdzie trzymane są uploady (czy katalog uploadu ma sensowne izolacje),
  • czy endpoint uploadu jest publiczny oraz jak wygląda autoryzacja/limity.

Rekomendacje operacyjne / co zrobić teraz

1) Aktualizacja (najważniejsze)

  • Zaktualizuj @adonisjs/bodyparser do 10.1.2 (lub nowszej) w gałęzi stabilnej.
  • Jeśli używasz pre-release 11.x: zaktualizuj do 11.0.0-next.6 (lub nowszej).

2) Szybki audyt kodu pod kątem podatnego wzorca

Priorytetowo przejrzyj miejsca, gdzie:

  • przyjmujesz upload multipart/form-data,
  • wywołujesz MultipartFile.move(...) bez jawnego options.name,
  • dopuszczasz overwrite: true (albo nie ustawiasz tego parametru).

3) Twarde zasady dla uploadów (defense-in-depth)

Nawet po aktualizacji:

  • Przechowuj uploady poza webrootem (aby nie dało się ich od razu wykonywać/serwować jako kod).
  • Stosuj allowlistę typów (MIME i/lub sniffing), limity rozmiaru, limity liczby plików.
  • Używaj least privilege dla procesu Node.js (konto systemowe bez praw do katalogów aplikacji/konfiguracji).
  • Rozważ read-only filesystem dla kontenera i osobny, izolowany wolumen tylko na uploady.

4) Monitoring i detekcja (co sprawdzić po stronie SOC/ops)

  • Nietypowe zapisy plików poza katalogiem uploadu (auditd/EDR/file integrity monitoring).
  • Zmiany w plikach konfiguracyjnych, startup scriptach, plikach .env, artefaktach buildu.
  • Logi aplikacji i reverse proxy pod kątem podejrzanych nazw plików w multipart (sekwencje ../, %2e%2e%2f, mieszane separatory).

Różnice / porównania z innymi przypadkami (jeśli dotyczy)

Ten incydent dobrze pokazuje różnicę między:

  • „podatnością w samej walidacji ścieżki” a
  • „podatnością wynikającą z niebezpiecznych domyślnych ustawień API”.

Tutaj kluczowe było to, że bezpieczne zachowanie wymagało od programisty dodatkowej pracy (podania options.name lub sanitacji), a brak tej pracy prowadził do ryzykownego defaultu. Advisory dodatkowo wskazuje, że dokumentacja wcześniej mogła kierować w stronę tej podatnej ścieżki.

To częsty wzorzec w lukach uploadowych: nawet jeśli programista „zapisuje do katalogu uploadów”, wystarczy jedna nieprzemyślana decyzja o budowaniu ścieżki z danych od klienta, aby pojawił się path traversal.

Podsumowanie / kluczowe wnioski

  • CVE-2026-21440 (CVSS 9.2) to krytyczna luka typu path traversal w obsłudze uploadów w @adonisjs/bodyparser, umożliwiająca dowolny zapis/nadpisanie plików na serwerze.
  • Eksploatacja wymaga osiągalnego endpointu uploadu i podatnego użycia MultipartFile.move() bez bezpiecznych opcji.
  • Najlepsza reakcja to natychmiastowa aktualizacja do 10.1.2 (lub 11.0.0-next.6) oraz szybki przegląd miejsc, gdzie aplikacja zapisuje uploady na dysk.

Źródła / bibliografia

  • GitHub Security Advisory: AdonisJS Path Traversal in Multipart File Handling (GHSA-gvq6-hvvp-h34h). (GitHub)
  • NVD / NIST: CVE-2026-21440. (NVD)
  • GitHub Releases: adonisjs/bodyparser v10.1.2 (opis zmiany domyślnej nazwy pliku na uuid). (GitHub)
  • The Hacker News: omówienie podatności i warunków eksploatacji (06 stycznia 2026). (The Hacker News)