Przejdź do treści
INDEKS ANALIZ BREACHROAD / NOTA TECHNICZNA

Headroom LLM proxy: nagłówek wybiera cudzą pamięć i prywatny upstream

CVE-2026-77775 i 77776 ujawniają SSRF z forwardingiem Authorization oraz cross-user memory access w proxy LLM wystawionym przez docker-compose.

MATERIAŁ PUBLICZNY
AUTOR
/ CEO Breachroad · OSCP · PNPT
PUBLIKACJA
21 sierpnia 2026
CZAS CZYTANIA
19 min czytania
TEMAT
Bezpieczeństwo AI
Headroom LLM proxy: nagłówek wybiera cudzą pamięć i prywatny upstream

21 sierpnia opublikowano dwa CVE dla Headroom, proxy optymalizującego ruch do modeli językowych. CVE-2026-77776 pozwala klientowi podać x-headroom-user-id i czytać lub modyfikować pamięć innego użytkownika. CVE-2026-77775 pozwala przez x-headroom-base-url wybrać upstream HTTP/HTTPS, w tym loopback, RFC 1918, link-local lub metadata service; odpowiedź wraca do klienta, a nagłówek Authorization może zostać przesłany do wybranego hosta.

Ryzyko zwiększa rozjazd między lokalnym CLI a referencyjnym wdrożeniem. Skrypt pip domyślnie wiąże usługę do 127.0.0.1, lecz dostarczony docker-compose.yml publikował port na 0.0.0.0 bez obowiązkowego HEADROOM_PROXY_TOKEN. Serwer ostrzegał o takiej konfiguracji, ale przykład ułatwiał stworzenie sieciowo osiągalnej płaszczyzny danych bez uwierzytelnienia.

CVE-2026-77776: identyfikator nie jest tożsamością

Handler chat completion i ścieżka WebSocket odczytywały x-headroom-user-id bez związania wartości z callerem. Klient mógł nazwać identyfikator innej osoby i uzyskać dostęp do jej zapisanej pamięci LLM. CVSS 4.0 wynosi 9,3: atak sieciowy, niska złożoność, brak wymaganego konta i wysoki wpływ na poufność oraz integralność danych pamięci.

To podręcznikowy błąd multi-tenancy. Nagłówek może być atrybutem przekazanym przez zaufany gateway, ale tylko jeśli proxy usuwa nagłówki klienta, gateway uwierzytelnia użytkownika, podpisuje lub ustawia wartość i istnieje jednoznaczna granica zaufanych źródeł. Bez tego identyfikator jest danymi wejściowymi, nie dowodem tożsamości.

Poprawka wprowadza centralne resolve_memory_identity(). Dla zdalnych callerów pamięć jest wiązana z fingerprintem tokenu proxy lub użytkownikiem systemowym, a nagłówek może być honorowany tylko z loopback albo zatwierdzonej ścieżki. Jedna funkcja rozstrzygająca jest bezpieczniejsza niż sześć niezależnych odczytów nagłówka.

CVE-2026-77775: proxy jako SSRF z odbiciem odpowiedzi

Funkcje wybierające OpenAI upstream akceptowały wartość x-headroom-base-url, sprawdzały jedynie schemat HTTP/HTTPS i obecność hosta, a potem wykonywały żądanie. Nie odrzucały loopback, link-local ani prywatnych zakresów. Ponieważ Headroom jest proxy, odpowiedź upstream wracała do klienta. To silniejszy wariant blind SSRF: napastnik może zobaczyć rezultat.

Dodatkowo Authorization był forwardowany bez zmiany do hosta wybranego przez klienta. Jeżeli użytkownik wysłał token dostawcy LLM, atakujący mógł skierować żądanie do własnego serwera i przejąć nagłówek. W chmurze celem mogła być usługa metadanych, a w klastrze wewnętrzny panel lub API osiągalne tylko z sieci proxy.

Poprawka upstream_guard.is_safe_upstream_url() blokuje adresy metadata, RFC 1918, loopback i link-local na wszystkich wejściach base URL. Dopuszczenie prywatnego dostawcy wymaga jawnej allowlisty HEADROOM_ALLOWED_BASE_URLS. Ważna jest walidacja po DNS resolution i dla każdego redirectu, ponieważ sama kontrola tekstowej nazwy hosta jest podatna na rebinding i zmianę celu.

Siedem poprawek, nie tylko dwa CVE

Merge bezpieczeństwa #2207 obejmuje siedem ustaleń. Oprócz SSRF i tożsamości pamięci dodano SHA-256 pinning pięciu pobieranych binariów narzędziowych, ograniczono endpoint importu telemetry i 15 operacyjnych GET do loopback, utwardzono compose, usunięto domyślne hasła Neo4j i ograniczono ekstrakcję tar przez filter="data".

To ważne, bo ryzyka się łączą. Brak tokenu na publicznym bindzie zmieniał lokalne błędy w zdalne. Niezweryfikowane binaria tworzyły łańcuch dostaw. Szerokie endpointy operacyjne ujawniały stan. Ocena tylko dwóch numerów CVE może pominąć konfigurację, która nadal pozostawia niepotrzebny attack surface.

Jak sprawdzić, czy wdrożenie jest narażone

Zidentyfikuj wersję obrazu, commit lub release zawierający merge #2207. Nie zakładaj, że latest oznacza poprawkę; zapisz digest. Sprawdź effective compose config, bind address, publikowane porty, reverse proxy i obecność HEADROOM_PROXY_TOKEN. Ustal, czy proxy jest osiągalne z Internetu, sieci firmowej, innych namespace Kubernetes lub współdzielonego hosta.

Przejrzyj, czy klienci wysyłają x-headroom-user-id i x-headroom-base-url, kto je ustawia oraz czy ingress usuwa wartości pochodzące od użytkownika. Zmapuj storage pamięci, retencję i identyfikatory tenantów. Dla upstream ustal dozwolonych dostawców, DNS, porty i egress proxy. Własny endpoint LLM w RFC 1918 wymaga jawnej, wąskiej reguły, nie wyłączenia ochrony SSRF.

Bezpieczna aktualizacja i konfiguracja

Wdróż wydanie zawierające merge #2207 lub nowsze, potwierdzone przez maintainerów. Ustaw obowiązkowy silny HEADROOM_PROXY_TOKEN, bind do loopback lub prywatnego interfejsu i uwierzytelniony reverse proxy. Nie publikuj Neo4j ani paneli operacyjnych. Egress ogranicz do zatwierdzonych origins dostawców LLM, z uwzględnieniem scheme, host i port.

W systemie wieloużytkownikowym nie używaj dowolnego nagłówka jako identity. Gateway powinien uwierzytelnić klienta i przekazać niepodrabialny principal, a proxy zastosować custom identity resolver. Pamięć musi być partycjonowana tym samym identyfikatorem na odczycie, zapisie, WebSocket, retry i narzędziach.

Test regresji powinien potwierdzić, że zdalny klient nie może wybrać obcego user ID, adresu prywatnego, loopback, link-local, metadata ani innego portu na allowlisted host. Sprawdź redirect oraz odpowiedzi DNS zmieniające się między walidacją i połączeniem. Nie testuj metadata service w produkcji; użyj kontrolowanego serwera imitującego klasy adresów w izolowanym środowisku.

Hunting i skutki po ekspozycji

W access logs szukaj x-headroom-base-url wskazujących nietypowe domeny, adresy IP, porty i schematy, a także odpowiedzi z formatem charakterystycznym dla usług wewnętrznych. Przejrzyj outbound DNS i HTTP proxy z poda Headroom. Jeśli Authorization mógł trafić do obcego hosta, rotuj konkretny token dostawcy i sprawdź jego użycie.

Dla pamięci szukaj jednego źródła zmieniającego wiele x-headroom-user-id, operacji na tenantach niepowiązanych z callerem i zmian pamięci bez odpowiadającej sesji. Ustal, czy dane zawierały prompty, fragmenty dokumentów, decyzje agentów lub informacje osobowe. Nie zakładaj, że pamięć jest „tylko cache”; może wpływać na przyszłe odpowiedzi i działania.

Patching nie cofa ujawnienia. Zabezpiecz logi, snapshot storage i konfigurację, a następnie usuń obce wpisy dopiero po zachowaniu dowodów. Jeżeli pamięć mogła być zatruta, trzeba ją zwalidować lub odbudować z zaufanego źródła, nie tylko zmienić token.

Telemetria bez kolejnego wycieku

Logowanie pełnych nagłówków ułatwia hunting, ale może samo ujawnić Authorization, identyfikator użytkownika i treść promptu. Rejestruj nazwę docelowego origin, wynik polityki, hash principalu, status i latency, natomiast tokeny zawsze redaguj. Dostęp do logów proxy powinien być węższy niż zwykły dostęp developerski.

Dla pamięci zapisuj zdarzenia odczytu i zapisu z tenantem, wersją resolvera oraz niezmiennym request ID. Audyt nie powinien zawierać całego dokumentu, lecz musi pozwalać wykazać, kto przekroczył granicę. Taki model skraca analizę CVE bez tworzenia wtórnego magazynu wrażliwych danych.

Fakty projektu i wnioski Breachroad

Mechanizmy CVE, domyślny bind CLI, ryzykowny compose, zakres merge #2207 i nowe zmienne pochodzą z publicznych rekordów oraz repozytorium Headroom. CVE nie informują o aktywnej eksploatacji. Wybór bezpiecznego release powinien zostać potwierdzony w changelogu projektu, ponieważ rekord opisuje kod i merge, a nie pełną macierz dystrybucji.

Zasady gateway identity, pełna walidacja origin, hunting i odbudowa pamięci są analizą Breachroad. Szkolenia bezpieczeństwa AI uczą rozpoznawać te granice, a audyt bezpieczeństwa AI może sprawdzić proxy, multi-tenancy, pamięć, tokeny i egress.

Źródła

UDOSTĘPNIJ / KOPIUJ