Na październikowym SAP Security Patch Day (13.10.2026) najwyższą ocenę dostała podatność, której nie ma w żadnym systemie SAP. CVE-2026-89111 (note 3797111, CVSS 10.0) siedzi w SAP Cloud SDK for Python, czyli w pakiecie sap-cloud-sdk z PyPI, który instalujesz w swoich aplikacjach na BTP. Kto kontroluje parametr tenant_subdomain, może skierować żądanie tokenu OAuth2 na własny serwer i przechwycić client credentials aplikacji. Tego findingu nie zamkniesz przez SNOTE. Trzeba go znaleźć w requirements.txt, w lockfile’u albo w SBOM.
AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N = 10.0, CWE-918.sap-cloud-sdk (moduł sap_cloud_sdk, repozytorium SAP/cloud-sdk-python). Podatne < 0.45.2, poprawione w 0.45.2. Tak podają jednocześnie strona Patch Day, NVD i advisory w repozytorium SAP („patched_versions: 0.45.2”).tenant_subdomain przekazywaną do SDK.Attack path
Advisory jest krótkie: kto kontroluje tenant_subdomain, może przekierować żądania tokenu OAuth2 na serwer, który sam kontroluje, a to prowadzi do wycieku client credentials. Release notes wersji 0.45.2 dopowiadają, które miejsca poprawiono: AgentGatewayClient._resolve_tenant_subdomain, destination.TokenProvider.get_token i dms.Auth._resolve_token_url. Wartość jest teraz sprawdzana według reguł etykiety DNS z RFC 1123, a kropki, ukośniki, spacje, podkreślenia i ciągi dłuższe niż 63 znaki kończą się błędem ValueError. Wcześniej, jak piszą sami autorzy, nieprawidłowe wartości były „silently used to construct a malformed URL”. Wniosek dla VE: punktem wejścia jest nie SDK samo w sobie, tylko to, skąd Twoja aplikacja bierze subdomenę tenanta. Mechanizm przypomina znany z LiteLLM wzorzec, w którym klient sam dołącza sekrety do żądania wysłanego pod adres podany przez atakującego.
Dlaczego klasyczny proces SAP tego nie zobaczy
W wielu organizacjach patch management SAP wygląda tak: co miesiąc lista SAP notes, dopasowanie do komponentów i Support Package’ów, wdrożenie przez SNOTE albo SPAM/SUM. Ten proces działa na systemach. CVE-2026-89111 nie dotyczy żadnego systemu: to biblioteka zainstalowana przez pip w aplikacji, którą napisał Twój zespół albo partner, zbudowana w Twoim CI i wdrożona na Cloud Foundry lub Kyma. Note 3797111 nie ma czego „zaimplementować” w systemie SAP. Właścicielem findingu jest więc zespół aplikacji, a nie Basis, a skaner infrastruktury nie zajrzy do obrazu kontenera ani do lockfile’a w repozytorium.
Jest jeszcze druga pułapka, tym razem po stronie SCA. Według danych pobranych 16.10 baza GitHub Advisory ma dla tego CVE globalny rekord GHSA-m3j7-wp2j-mhc3, który jest „unreviewed” i ma pustą listę podatnych pakietów. Rekord z prawdziwym zakresem wersji (pip / sap-cloud-sdk / <0.45.2) to advisory w repozytorium SAP, czyli GHSA-4mv3-jxxm-9cx2. Zapytanie do OSV o sap-cloud-sdk 0.45.1 (PyPI) zwraca pusty wynik, a sam rekord OSV dla CVE-2026-89111 ma zakres zapisany jako tekst "sap-cloud-sdk < 0.45.2" zamiast wersji pakietu. PyPI też nie pokazuje podatności przy wersji 0.45.1. W praktyce narzędzia opierające się na tych źródłach mogą na razie nie zgłosić podatnej wersji. Nie sprawdzałem każdego skanera, ale „Dependabot milczy” nie dowodzi tu, że problemu nie ma. Ten sam rozjazd między GHSA a resztą ekosystemu opisywałem przy Flatpaku i h3.
Jak znaleźć pakiet
Dopóki bazy SCA nie mają poprawnego zakresu wersji, szukaj nazwy pakietu i porównuj wersję ręcznie. Pip normalizuje nazwy, więc w plikach może się pojawić sap-cloud-sdk, sap_cloud_sdk albo SAP-Cloud-SDK.
Uwaga na zapisy bez górnego limitu, np. sap-cloud-sdk>=0.40 w requirements.txt: wersję w produkcji wyznacza wtedy lockfile albo dzień ostatniego buildu, a nie manifest. Jeśli nie masz lockfile’a, sprawdzaj obraz, który faktycznie działa. To samo zjawisko, tylko w ekosystemie NPM, opisywałem przy SAP CAP multitenancy: biblioteka od SAP w aplikacji klienta potrafi stać się cross-tenant findingiem.
Remediation
sap-cloud-sdk 0.45.2 lub nowszy (na PyPI aktualna jest 0.59.0). Wymagany Python >= 3.11.tenant_subdomain względem allowlisty zarejestrowanych subdomen tenantów. Advisory nie podaje innych środków zaradczych.Workaround to zmiana w kodzie aplikacji, nie konfiguracja platformy. Wymaga więc przeglądu wszystkich miejsc, w których subdomena trafia do SDK. W praktyce upgrade jest zwykle prostszy. Allowlista ma sens tam, gdzie upgrade blokuje zgodność z innymi pakietami.
Rotacja sekretów to osobna decyzja
Upgrade zamyka podatność, ale nie unieważnia credentials, które mogły już wyciec. SAP nie zaleca rotacji wprost, w advisory jej nie ma. Skutkiem podatności jest jednak właśnie wyciek client credentials, a advisory nie podaje IoC. Jeśli więc aplikacja z podatną wersją działała w trybie multi-tenant, a tenant_subdomain mógł pochodzić z danych kontrolowanych z zewnątrz, rozsądnie jest założyć ekspozycję. Rotuj client secrets / klucze service bindings, których SDK używało do pobierania tokenów, i przejrzyj logi ruchu wychodzącego z aplikacji pod kątem żądań tokenów do hostów spoza oczekiwanych domen. Taki „kontekst sekretów” przy SSRF omawiałem przy AWX.
Na marginesie: CVE-2026-89110, Visual Composer 9.9
Ten sam Patch Day przyniósł też CVE-2026-89110 (note 3805589, CVSS 9.9, Broken Access Control) w SAP NetWeaver Visual Composer, VC70RUNTIME 7.50. Według NVD użytkownik o niskich uprawnieniach może wywołać wewnętrzne operacje na wcześniej skonfigurowanym systemie zdalnym, co zależnie od konfiguracji połączenia może skończyć się pełnym przejęciem tego systemu. To klasyczny finding po stronie systemu SAP, więc ten proces miesięczny zobaczy. Ciekawostka z jakości danych: rekord NVD dla 89110 w referencjach linkuje note 3797111 (czyli note od SDK), podczas gdy strona SAP Patch Day przypisuje 89110 do note 3805589. Przy automatycznym mapowaniu CVE→note trzymaj się strony SAP.
Co powinien zrobić VE
(1) Przeszukaj repozytoria, lockfile’y, SBOM-y i działające obrazy pod kątem sap-cloud-sdk i zapisz wersję każdej instancji. Nie czekaj, aż alert pojawi się sam. (2) Każdą aplikację z wersją < 0.45.2 przypisz do zespołu aplikacyjnego, nie do Basis. (3) Ustal, czy aplikacja jest multi-tenant i skąd bierze tenant_subdomain. To decyduje o priorytecie. (4) Upgrade do 0.45.2+, a do tego czasu allowlista według advisory SAP. (5) Przy realnej ekspozycji rotuj credentials. (6) Dodaj „biblioteki SAP w ekosystemach pip/npm/Maven” jako osobną kategorię w przeglądzie każdego SAP Patch Day. Strona SAP oznacza je wprost jako „Library” i osobno wylicza GitHub security advisories.
Powiązane na blogu
- SAP CAP multitenancy: biblioteka NPM od SAP jako cross-tenant finding
- LiteLLM CVE-2026-84377: SSRF, który wysyła klucze pod adres atakującego
- Flatpak: GHSA bez CVE: gdy bazy podatności się rozjeżdżają
Źródła
- SAP Security Patch Day — October 2026 (13.10.2026) — support.sap.com
- SAP/cloud-sdk-python — GHSA-4mv3-jxxm-9cx2: OAuth2 SSRF vulnerability in SAP Cloud SDK for Python — github.com
- SAP/cloud-sdk-python — release v0.45.2 (21.08.2026) — github.com
- PyPI — sap-cloud-sdk — pypi.org
- NVD — CVE-2026-89111 — nvd.nist.gov
- GitHub Advisory Database — GHSA-m3j7-wp2j-mhc3 (unreviewed) — github.com
- OSV — CVE-2026-89111 — osv.dev
- NVD — CVE-2026-89110 (SAP NetWeaver Visual Composer) — nvd.nist.gov
Nota redakcyjna: stan informacji 16 października 2026, na podstawie strony SAP Security Patch Day (13.10.2026), advisory GHSA-4mv3-jxxm-9cx2 w repozytorium SAP/cloud-sdk-python, release notes v0.45.2, PyPI, NVD i OSV. Treść SAP note 3797111 wymaga logowania do SAP for Me i nie była weryfikowana. Stan rekordów GitHub Advisory Database i OSV może się zmienić po ich przeglądzie. Zalecenie rotacji credentials to rekomendacja autora, nie zalecenie SAP.