GHSA-jrfj-fhj2-jjvm w bibliotece Excelize łączy trzy problemy, które SCA zwykle spłaszcza do jednego findingu: biblioteka ma podatny kod, exploitability zależy od pochodzenia plików, a popularny „compensating control” w postaci timeoutu HTTP może zakończyć odpowiedź klientowi, ale nie zakończyć kosztownej pracy CPU po stronie serwera.
spinCount w ścieżce agile decryption (github.com/xuri/excelize/v2).spinCount=100000000 → OpenFile pracuje ~58,65 s (Excelize 2.11.0) i i tak kończy błędem invalid zip; koszt ~0,6 µs/iterację (liniowo).Jak mały plik pali CPU
Excelize rozpoznaje kontener OLE po pierwszych ośmiu bajtach. Jeśli wejście wygląda jak zaszyfrowany dokument Office, OpenFile wchodzi w ścieżkę deszyfrowania — niezależnie od tego, czy aplikacja świadomie oferuje pracę z zaszyfrowanymi workbookami. Atakujący kontroluje spinCount, a kosztowny convertPasswdToKey wykonuje się przed weryfikacją, czy dane to poprawny workbook. Pamięć pozostaje stabilna — zasobem jest czas CPU, nie heap, więc klasyczne memory limits nie zatrzymają ataku.
Dlaczego HTTP timeout nie wystarcza
To najważniejszy detal dla VE. Kosztowna operacja nie ma context.Context, którym caller mógłby anulować pracę. Serwer HTTP może przekroczyć write timeout i zamknąć odpowiedź po kilku sekundach, ale goroutine wykonująca KDF nadal działa:
proxy_read_timeout 5s nie jest dowodem mitigacji — ogranicza czas życia połączenia, nie czas życia obliczenia.
Package affected ≠ application exploitable
Biblioteka nie nasłuchuje na sieci — network attack vector pojawia się, gdy aplikacja przyjmuje workbook od użytkownika i przekazuje go do OpenFile. Narzędzie otwierające wyłącznie pliki generowane wewnętrznie nie ma tego samego attack surface co publiczny SaaS analizujący pliki klientów. To dobry przykład dla VEX: ustal input trust, call-path reachability i runtime resource controls, zanim nadasz identyczne SLA każdej aplikacji z Excelize 2.11.0.
Brak patcha — inny workflow
W momencie publikacji advisory upstream nie wskazywał patched version. Nie wymyślaj numeru i nie przesuwaj findingu do Risk accepted tylko dlatego, że nie ma patcha. Lepszy model stanu: exploitable / no vendor fix → temporary mitigation applied → mitigation verified → awaiting upstream remediation.
Które compensating controls działają
Najsilniejsze odcinają lub ograniczają kosztowną ścieżkę, nie tylko kończą połączenie: odrzucanie plików OLE/encrypted przed Excelize (jeśli to nie funkcja biznesowa), uruchamianie parsera w osobnym procesie/jobie z twardym limitem CPU i deadline egzekwowanym przez supervisora, który może zabić proces, ograniczenie równoległości na tenant, kolejka z backpressure. Jeśli proces nie może zostać przerwany, sam timeout aplikacyjny jest control present, ale nie control effective.
Wniosek
Najważniejsze pytanie nie brzmi „czy mamy Excelize?”, tylko: czy niezaufany plik może uruchomić nieograniczoną pracę, której nasz system nie potrafi rzeczywiście przerwać? Jeśli tak, 504 to nie sukces. To dobry wzorzec do zapamiętania: timeout połączenia, deadline requestu i limit życia obliczenia to trzy różne kontrole.
Powiązane na blogu
- Go crypto/tls: KeyUpdate jako DoS — koszt asymetryczny po stronie serwera
- Zephyr: DoS i koszt recovery — availability i realny blast radius
Źródła
- qax-os/excelize — Security Advisory GHSA-jrfj-fhj2-jjvm (06.09.2026) — github.com/qax-os
Nota redakcyjna: stan informacji 7 września 2026. GHSA-jrfj-fhj2-jjvm (excelize/v2, CVSS 7.5 Availability): nieograniczony spinCount w agile decryption; kosztowny KDF biegnie przed walidacją i bez możliwości anulowania. W chwili publikacji brak patched version. Artykuł koncentruje się na różnicy między timeoutem połączenia a limitem życia obliczenia i na reachability niezaufanego pliku.