25 lipca 2026 trzyosobowy zespół firmy Hacktron wgrał zdjęcie na forum community.openai.com i w ciągu niecałych 72 godzin doszedł stamtąd do wewnętrznego repo OpenAI. Łańcuch prowadził przez bibliotekę do dekodowania obrazów, przestarzały pakiet w Debianie i błąd w logowaniu jednokrotnym. OpenAI wypłaciło 6500 dolarów. Szczegóły opublikowano 13 września.
Cały łańcuch ma dziewięć ogniw i żadne nie jest egzotyczne
Forum OpenAI działa na Discourse. Discourse przyjmuje wgrywane obrazy i sprawdza je biblioteką FastImage, ale FastImage nie obsługuje formatu HEIF, więc takie pliki trafiają do konwersji przez ImageMagick. ImageMagick woła libheif. W ten sposób plik od anonimowego użytkownika ląduje bezpośrednio w parserze napisanym w C.
W libheif był „heap buffer overflow” dający odczyt i zapis poza zakresem podczas dekodowania HEIC. Badacze opisują w swoim raporcie rzecz, która jest tu najważniejsza: podatny kod poprawiono w projekcie źródłowym rok wcześniej, ale commit nie został opisany jako poprawka bezpieczeństwa i nie dostał numeru CVE. Nikt więc nie zrobił backportu. Obraz Docker Discourse’a bazował na Debianie 12 i instalował libheif w wersji 1.19.7. Debian 13 w tym czasie miał 1.19.8 — również podatną.
Z RCE na forum badacze przeszli do przejęcia kont. Forum pozwala logować się przez „Sign in with OpenAI” przez auth.openai.com, a błąd w tej ścieżce tożsamości pozwolił przejąć konta ChatGPT i Codex pracowników aktywnych na forum — bez żadnej interakcji z ich strony. Jeden z przejętych Codexów miał podpiętą organizację GitHuba OpenAI. Żeby udowodnić dostęp bez czytania cudzego kodu, badacze kazali temu Codexowi otworzyć pull request w wewnętrznym repozytorium, po czym przerwali testy.
Problemem nie było forum, tylko to co za nim stało
Hacktron podkreśla to wprost: podatność umożliwiająca eskalację nie była specyficzna dla Discourse’a. Leżała w SSO OpenAI. Kompromitacja dowolnej usługi korzystającej z tego logowania własnej albo cudzej dawała ten sam efekt. Forum było tylko najwygodniejszym wejściem, bo miało parser obrazów.
To jest wzorzec, który w polskiej organizacji wygląda identycznie. Do firmowego Entra ID albo innego dostawcy tożsamości podpięte bywa wszystko: intranet, wiki, system zgłoszeń, narzędzie HR, forum społeczności, panel dostawcy. Każda z tych aplikacji ma inny poziom utrzymania i inny zespół — a często nie ma żadnego. Model zaufania jest natomiast wspólny: przejęcie najsłabszej aplikacji w tej liście oznacza przejęcie tożsamości pracownika, a wraz z nią wszystkich integracji, które ta tożsamość otwiera.
W tym przypadku integracją był Codex z dostępem do repozytoriów. Agent podpięty do konta pracownika jest z punktu widzenia napastnika lepszy niż samo konto: wykonuje polecenia, ma własne uprawnienia do systemów zewnętrznych i działa w tle.
Reakcja producentów i regresja, o której trzeba wiedzieć
Tu akurat proces zadziałał. OpenAI potwierdziło naprawę około 14 godzin po zgłoszeniu. Discourse dostał raport w sobotę, odpowiedział w niedzielę, w poniedziałek miał poprawkę, a 28 lipca opublikował advisory GHSA-vhm9-85gw-x335 z numerem CVE-2026-32882 i oceną CVSS 3.1 na poziomie AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H. Przy okazji dołożył izolację ImageMagicka jako warstwę obrony, czego wcześniej nie było.
Debian wydał DSA-6417-1 8 sierpnia, poprawiając w stabilnym wydaniu (trixie) dwanaście podatności libheif naraz, w wersji 1.19.8-1+deb13u1. W tym samym komunikacie jest zdanie, które łatwo przeoczyć, a które zepsuje komuś produkcję: przy poprawianiu CVE-2026-47178 odrzucono część kombinacji formatów. Obrazy nieskompresowane z podpróbkowaniem chrominancji 4:2:0 lub 4:2:2, kafelkowane albo używające przeplotu wierszy lub pikseli, przestaną się dekodować. Debian nie mógł wziąć właściwej poprawki, bo powstała dopiero po przebudowie dekodera, której w stabilnej wersji jeszcze nie ma. Jeżeli twoja aplikacja przetwarza takie pliki, aktualizacja bezpieczeństwa jest jednocześnie zmianą funkcjonalną.
Jest w tej historii również wątek, który warto odnotować. OpenAI, przyznając nagrodę, zaznaczyło, że testowanie forum utrzymywanego na Discourse było z zakresu programu bug bounty wyłączone, a wypłata dotyczy wyłącznie ustalenia po stronie OpenAI. Innymi słowy: element infrastruktury, przez który realnie weszli badacze, formalnie nie podlegał testom. Granice zakresu w programach zgłaszania podatności rzadko pokrywają się z granicami, po których porusza się napastnik.
Dwa miesiące, trzy osoby, mniej niż trzy tysiące dolarów
Badacze podają koszt swojej szerszej kampanii, w której ten sam wektor libheif prowadzili przeciwko kolejnym celom: dwa miesiące pracy trzech osób i poniżej 3000 dolarów za tokeny. Dostosowanie eksploita do nowej firmy zajmowało zwykle jeden lub dwa dni, zaczynając od samego wgrania obrazu, bez wiedzy o wersji biblioteki i środowisku docelowym.
Opisują też przeskok między modelami. Starszy model przez kilka sesji nie potrafił zbudować działającego eksploita przy włączonym ASLR. Nowszy, uruchomiony na tym samym problemie kilka godzin po premierze, dał działający wynik w trzy godziny. To nie jest twierdzenie o inteligencji modelu, tylko o cenie kompetencji: praca, która wymagała rzadkiego specjalisty i tygodni, zaczyna się przeliczać na godziny obliczeń.
I jeszcze jedno zdanie z tego raportu, warte zapamiętania osobno: spośród wszystkich atakowanych firm aktywność wykrył tylko jeden podmiot — Shopify. Pozostałe nie zareagowały mimo tysięcy przesłanych obrazów i powtarzających się awarii procesorów obrazu.
Dla podmiotu objętego NIS2 albo ustawą o krajowym systemie cyberbezpieczeństwa to jest dokładnie ten obszar, który przepisy nazywają bezpieczeństwem łańcucha dostaw, a który w praktyce sprowadza się do pytania: czy wiesz, jakie biblioteki działają w obrazach twoich kontenerów, i czy masz proces, który reaguje na poprawkę wydaną bez numeru CVE. Odpowiedź „mamy skaner podatności” nie wystarcza, bo skaner porównuje wersje z bazą identyfikatorów, a w tym przypadku identyfikatora przez rok nie było.
Co z tego wynika dla Twojej organizacji?
- Ustal, co u ciebie dekoduje obrazy przysłane z zewnątrz, i sprawdź wersję libheif w kontenerze, nie na hoście. Dotyczy to forów, systemów zgłoszeń, portali dla klientów, wszystkiego, co przyjmuje załącznik graficzny. Jeśli prowadzisz własną instancję Discourse’a, aktualizacja z poziomu interfejsu może nie wymienić obrazu Dockera potrzebny jest git pull i pełna przebudowa poleceniem ./launcher rebuild app z katalogu instalacji. Wersję sprawdź poleceniem dpkg wewnątrz kontenera; na trixie ma być 1.19.8-1+deb13u1 lub nowszy.
- Wypisz wszystkie aplikacje podpięte do twojego dostawcy tożsamości i zaznacz te, których nie utrzymujesz. W Entra ID zrób to na liście rejestracji aplikacji i aplikacji korporacyjnych, sprawdzając przy każdej, jakie uprawnienia delegowane otrzymała i kto odpowiada za jej łatanie. Dla aplikacji zewnętrznych, forów i narzędzi społecznościowych rozważ osobny krąg tożsamości zamiast konta pracowniczego. Zakładasz, że każda z nich zostanie kiedyś przejęta, i projektujesz tak, żeby to nie oznaczało przejęcia pracownika.
- Sprawdź, czy awarie procesu przetwarzającego obrazy w ogóle docierają do twojego kolektora logów. Powtarzający się crash konwertera przy wgrywaniu pliku to w tym scenariuszu jedyny sygnał, jaki ofiara dostaje przed wejściem. Jeśli te zdarzenia lądują wyłącznie w logu aplikacji i nikt ich nie zlicza, nie masz czego wykrywać. Ustaw próg na liczbę takich awarii w oknie czasowym i podepnij go pod alert.
Commit bez CVE zdejmuje więcej systemów niż niejeden zero-day
Z całej tej historii najtrwalszy jest pierwszy element łańcucha. Ktoś rok wcześniej poprawił błąd w bibliotece i nie oznaczył tego jako poprawki bezpieczeństwa. Bez etykiety nie było CVE, bez CVE nie było backportu w dystrybucji, bez backportu podatny kod wjechał do obrazu Dockera, który pobrały tysiące instalacji. Cała branżowa machina reagowania na podatności — skanery, katalogi, terminy, raporty zgodności — pracuje na strumieniu identyfikatorów. Podatność bez identyfikatora jest dla niej niewidzialna.
Napastnik nie korzysta z tego strumienia, po prostu czyta commity.