Strona główna / Blog / h3: GHSA miesiące przed CVE

Blog · analiza

h3: GHSA było publiczne w marcu, CVE pojawiło się dopiero we wrześniu. Kiedy CVE-only Vulnerability Management ma pół roku opóźnienia

Dwie podatności w popularnym frameworku HTTP dla Node.js (h3) były publicznie opisane w GitHub Security Advisories już w marcu 2026 — z affected versions, patched versions, attack path i PoC. Do szerokich CVE feedów trafiły jako CVE-2026-86250 i CVE-2026-86251 dopiero 6 września. To prawie pół roku różnicy między momentem, gdy techniczna wiedza była publiczna, a momentem, gdy pipeline oparty na CVE mógł ją automatycznie zobaczyć.

GHSA-q5pr-72pq-83v3 (21.03.2026): nieograniczony licznik chunków cookie → O(n²) w cleanup; fix ≥ 2.0.1-rc.18.
GHSA-72gr-qfp7-vwhw (20.03.2026): path traversal w serveStatic (przetrwałe percent-encoded dot segments); fix linii 1.x ≥ 1.15.9.
CVE: 86250/86251 opublikowane dopiero 06.09.2026.

27 bajtów requestu i O(n²) po stronie serwera

Wartość cookie mogła deklarować liczbę chunków przez sentinel typu __chunked__999999. Kod parsował liczbę bez sensownego górnego limitu, a kolejne operacje set/delete przechodziły ponownie przez istniejące nagłówki Set-Cookie — zachowanie zbliżone do O(n²). Pojedynczy request Cookie: h3=__chunked__999999 w aplikacji używającej sesji może zablokować proces Node.js; skoro event loop jest współdzielony, availability impact bywa większy niż „tylko DoS”.

Path traversal — ale tylko przy konkretnym backendzie

Sekwencja %252e%252e po jednym etapie normalizacji mogła pozostać jako %2e%2e, a resolveDotSegments() szukało literalnych kropek. Czy to od razu odczyt /etc/passwd? Nie — problem staje się groźny, gdy wynikowy asset ID trafia do backendu opartego na URL (CDN, S3), który ponownie interpretuje %2e%2e jako ..:

component vulnerable = yes reachable vulnerable utility = maybe backend interprets encoded dot segments = required actual exploitability = deployment dependent

CVE nie jest początkiem życia podatności

Jeśli organizacja uruchamia SCA wyłącznie na podstawie NVD/CVE, dziś dostaje finding i uznaje go za „nowy”. Tymczasem security-aware projekt miał tę informację od marca. Dla VE powstaje więc kilka różnych dat, których nie wolno zlewać w jedno published_at:

disclosure_date advisory_date cve_publication_date fix_available_date scanner_detection_date organization_first_seen_date

Czy to false negative?

Jeśli skaner deklaruje, że wykrywa wyłącznie CVE — formalnie nie. Jeśli organizacja oczekuje identyfikowania publicznie znanych podatności w zależnościach — praktycznie tak. To rozróżnienie kontraktowe: „No CVE found” nie oznacza „no known vulnerability”. Nowoczesny SCA/VM powinien mapować GHSA → package ecosystem → version range niezależnie od tego, czy istnieje CVE.

A VEX?

Ten przypadek pokazuje, że VEX nie może być tylko odpowiedzią na CVE ID. Dla serveStatic sensowne bywa not_affected / vulnerable_code_not_in_execute_path (serveStatic nieużywane) albo affected / condition: URL-based static backend. Jeśli system VEX nie potrafi pracować z GHSA bez CVE, przez kilka miesięcy nie ma czym formalnie opisać affectedness.

Wniosek

Największym problemem nie jest to, że CVE opublikowano później — lecz pipeline, który uznaje CVE za jedyny dopuszczalny identyfikator wiedzy o podatności. Realny VE mierzy też time_from_public_disclosure_to_detection; jeśli ta wartość zależy od tego, kiedy ktoś nada numer CVE, „zielony” dashboard może oznaczać tylko spóźnione źródło danych.

Powiązane na blogu

Źródła

Nota redakcyjna: stan informacji 7 września 2026. CVE-2026-86250/86251 (h3): dwa GHSA (chunked-cookie DoS, path traversal w serveStatic) publiczne 20–21 marca 2026, CVE dopiero 6 września — ~5,5 miesiąca luki. Artykuł koncentruje się na tym, że CVE nie jest początkiem życia podatności i że SCA/VEX muszą pracować z GHSA bez CVE.

Zapamiętaj jedno

CVE nie jest początkiem życia podatności. Jeśli pipeline uznaje CVE za jedyny dopuszczalny identyfikator wiedzy, organizacja może być „zielona” w dashboardzie tylko dlatego, że jej źródło danych jest spóźnione. Mierz nie tylko time_to_patch, ale time_from_public_disclosure_to_detection.