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ć.
≥ 2.0.1-rc.18.serveStatic (przetrwałe percent-encoded dot segments); fix linii 1.x ≥ 1.15.9.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 ..:
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:
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
- Ubuntu PAM: fix bez CVE — VM to nie CVE Management
- GHES: GHSA „Unknown” — jakość i kompletność danych o podatności
Źródła
- h3 — GHSA-q5pr-72pq-83v3 (21.03.2026) — github.com/h3js
- h3 — GHSA-72gr-qfp7-vwhw (20.03.2026) — github.com/h3js
- GitHub Advisory Database — CVE-2026-86250 / CVE-2026-86251 (06.09.2026) — github.com/advisories
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.