Strona główna / Blog / Fastify: malformed URL omija auth

Blog · case study

Fastify: globalny auth hook nie wystarcza. Malformed URL może przeskoczyć do prywatnego not-found handlera i ominąć cały request lifecycle

CVE-2026-76169 w Fastify to nie „CVSS 7.5, zaktualizuj pakiet”. Sedno jest ciekawsze: aplikacja może mieć poprawnie zadeklarowane mechanizmy autoryzacji, a mimo to specjalna ścieżka routingu dla niepoprawnego URL-a może ich nie wykonać. Control configured nie jest tym samym co control executed on every reachable request path.

CVE-2026-76169 (CVSS 7.5, Fastify 4.0.0–<5.12.2): ścieżka obsługi malformed URL trafiała do customowego not-found handlera innego („sibling”) pluginu, bez normalnego lifecycle — więc bez jego preHandler.
Root cause: malformed target trafiał do obsługi błędu zanim zakończono dekodowanie URL i wybór trasy; współdzielony wskaźnik do handlera naruszał enkapsulację prefiksów.

Attack path

aplikacja ma publiczny i chroniony obszar routingu chroniony ma setNotFoundHandler() z preHandler sprawdzającym usera → atakujący wysyła malformed request target → wewnętrzna ścieżka błędnego URL wybiera zły not-found handler → normalny lifecycle nie wykonuje się → handler zwraca odpowiedź bez kontroli dostępu

CVE nie mówi więc tylko „routing wybrał zły handler”. Mówi: security boundary zbudowano na założeniu, że każdy request do handlera zawsze przejdzie przez określone hooki — a to założenie było fałszywe.

Globalny onRequest nie jest tu compensating control

To jeden z najważniejszych punktów advisory: upstream wprost zaznacza, że globalny onRequest authentication hook nie mitigował tej podatności, bo malformed-URL path omijał normalny lifecycle. Łatwo wyobrazić sobie błędną analizę: „używamy podatnej wersji, ale auth mamy globalnie w onRequest, więc obniżmy finding”. Compensating control nie może być uznany za skuteczny tylko dlatego, że istnieje w kodzie — trzeba wykazać, że znajduje się przed podatnym punktem na rzeczywistej ścieżce ataku.

Severity to nie exploitability; reverse proxy jako virtual patch

Samo posiadanie Fastify 5.11.x nie wystarcza do oceny ryzyka. VE ustala: czy są customowe setNotFoundHandler() w encapsulated pluginach, czy któryś fallback zakłada wcześniejsze uwierzytelnienie, czy atakujący może wysłać surowy malformed target bez odrzucenia na proxy. Odrzucanie malformed targets na proxy/gateway bywa skutecznym obejściem — ale tylko po weryfikacji na dokładnie tej klasie wejścia i przy pewności, że backend nie jest osiągalny z pominięciem proxy.

Remediation i weryfikacja security property

Fix to Fastify 5.12.2: malformed URLs są kierowane do dedykowanych ścieżek onBadUrl/onMaxParamLength i kończą fail-closed zanim request trafi do aplikacyjnego not-found handlera; usunięto też współdzielony wskaźnik. Weryfikacja to nie npm list fastify — trzeba potwierdzić, że malformed request nie wchodzi do chronionego fallbacku (test wobec publicznych i prywatnych prefiksów, przez rzeczywisty ingress, nie tylko localhost). To różnica między patch verification a security-property verification.

VEX zależny od konfiguracji

Pakiet w podatnym zakresie jest affected, ale aplikacja może nie być exploitable, jeśli nie używa customowych not-found handlerów albo żaden nie zwraca danych wymagających auth — poparte dowodem architektonicznym i testem, nie intuicją. Uwaga: dodanie nowego pluginu lub handlera może zmienić affectedness bez zmiany wersji Fastify.

Wniosek

Najważniejsza lekcja to nie „zaktualizuj Fastify do 5.12.2”, lecz: autoryzacja jest skuteczna tylko wtedy, gdy istnieje na każdej ścieżce wykonania prowadzącej do chronionego efektu. VE pyta: czy ten konkretny request rzeczywiście przejdzie przez tę kontrolę?

Powiązane na blogu

Źródła

  • Fastify — Security Advisory GHSA-p68q-wchp-6fh7 / CVE-2026-76169 (04.09.2026) — github.com/fastify

Nota redakcyjna: stan informacji 7 września 2026. CVE-2026-76169 (Fastify 4.0.0–<5.12.2, CVSS 7.5): malformed URL trafiał do not-found handlera sibling pluginu z pominięciem lifecycle i preHandler; globalny onRequest nie mitigował; fix 5.12.2 (onBadUrl fail-closed). Artykuł koncentruje się na tym, że kontrola musi być wykonana na każdej osiągalnej ścieżce.

Zapamiętaj jedno

Autoryzacja jest skuteczna tylko wtedy, gdy istnieje na każdej ścieżce wykonania prowadzącej do chronionego efektu. Hook w kodzie, zapis w dokumentacji ani nawet globalny mechanizm auth nie są dowodem — VE pyta: czy ten konkretny request rzeczywiście przejdzie przez tę kontrolę?