SAP has disclosed a critical flaw in its Cloud SDK for Python that lets anyone who controls the tenant subdomain value send an application's OAuth2 token requests to a server they run. That request carries the application's own client ID and client secret.
What happened
The GitHub advisory GHSA-4mv3-jxxm-9cx2, published October 13, 2026, covers CVE-2026-89111 in the sap-cloud-sdk package on PyPI. SAP rates it Critical, CVSS 3.1 score 10.0, and classifies it as server-side request forgery (CWE-918). No privileges or user interaction are needed.
The affected scenario is multi-tenant applications on SAP Business Technology Platform (BTP). The SDK builds the token URL by substituting a tenant_subdomain value into it. Older versions did not validate that value, so an attacker who can influence it can point the token request at their own host and collect the credentials. Per the advisory, the fix validates tenant_subdomain against RFC 1123 DNS label rules before it goes into the token URL.
The version picture is messier than the advisory's headline range. The advisory lists versions below 0.45.2 as affected and 0.45.2 as patched. The Hacker News reports that the check was lost again in 0.53.0, when the Destination service module moved to new shared token-request code. It says Document Management Service calls in 0.55.0 also skipped the check, and that 0.36.1 and 0.36.2, released in September after the August fix, also lack it. According to THN, the full fix is in 0.55.1 (September 18) and later.
| Version | Status (per advisory and The Hacker News) |
|---|---|
| Below 0.45.2, including 0.36.1 and 0.36.2 | Vulnerable |
| 0.45.2 up to (not including) 0.53.0 | Check present |
| 0.53.0 to 0.55.0 | Vulnerable (regression) |
| 0.55.1 and later | Fixed |
A GitHub user, SunandM, reported the issue. THN notes the first fix shipped on August 21 under "Bug Fixes" in the release notes with no mention of security, 53 days before public disclosure. THN reports no known attacks.
Why it matters
The asset at risk is a non-human identity: the OAuth client credentials the application uses to authenticate itself to BTP services. A client secret is long-lived and is not tied to a user session. Anyone holding it can request tokens as the application until the secret is rotated.
This is the same pattern seen in the MCP Python SDK OAuth flaw: client code trusting an input to decide where to send its credentials. In multi-tenant apps, a tenant identifier often comes from a request, a hostname or a subscription callback, so it is easy to treat as internal data when an attacker can actually shape it. Between the unlabeled first fix and the later regression, teams that rely on release notes or a single version check could believe they are patched when they are not. SAP did not say whether apps that ran vulnerable versions should rotate credentials, so that call is yours.
What to check in your environment
- Inventory
sap-cloud-sdkusage. Find every BTP application and service that depends on the package, including transitive pins, and record the exact version deployed. - Upgrade to 0.55.1 or later. Moving to 0.45.2 is not enough for anyone on 0.53.0 to 0.55.0, and 0.36.x maintenance releases are not safe either.
- Add an allowlist check if you can't upgrade yet. The advisory's workaround is to validate
tenant_subdomainagainst your registered tenant subdomains before passing it to any SDK call. - Trace where the subdomain value comes from. For each app, confirm whether
tenant_subdomaincan be influenced by a request header, URL, or user-supplied field. Those apps carry the real exposure. - Rotate client secrets where exposure was possible. If a vulnerable version ever accepted an untrusted subdomain, rotate the affected OAuth client credentials after upgrading.
- Review egress and token activity. Look for outbound token requests to hosts outside your expected BTP authentication domains, and for token issuance to those client IDs from unfamiliar sources.
- Watch security advisories, not just release notes. Subscribe to the repository's security advisories so silent fixes and regressions don't get missed.