Threat Overview
Confirmed vendor disclosure (SAP GitHub advisory, October 13, 2026): CVE-2026-89111 is an OAuth2 server-side request forgery in sap-cloud-sdk for Python used by multi-tenant SAP Business Technology Platform applications. When an attacker controls the tenant_subdomain parameter, affected SDK token-URL construction can redirect an OAuth2 token request to an attacker-controlled server and transmit application client credentials. This is credential exfiltration through a token request, not a confirmed remote code execution flaw. SAP lists versions <0.45.2 as affected and 0.45.2 as patched; an allowlist of registered tenant subdomains is a vendor workaround.
Version qualification / researcher finding: The Hacker News (October 13) tested later releases and found missing validation in some Destination/Document Management Service code paths in 0.53.0–0.55.0; validation was restored in 0.55.1. SAP’s published advisory did not explicitly include those later releases as affected. Treat that later-version risk as independently reported and not yet reconciled with SAP’s CVE affected-version list.
MSSP relevance: Applications with a privileged OAuth client can leak secrets through ordinary-looking HTTPS egress. Sentinel network telemetry usually sees domains and process names, not HTTPS request bodies or client-secret values; application-level token request logs and accurate SDK dependency inventory are important.
References
- SAP official GitHub security advisory — 2026-10-13
- The Hacker News version testing — 2026-10-13
- SAP Cloud SDK Python repository release notes
- NVD CVE record
Impacted Systems
- Vendor/package: SAP Cloud SDK for Python, PyPI package
sap-cloud-sdk; relevant OAuth2 token provider, Agent Gateway, Destination and Document Management Service integrations. - Deployment: multi-tenant applications on SAP Business Technology Platform (BTP) using the Python SDK; host OS/container runtime is not itself the vulnerability boundary.
- Confirmed affected: package versions below 0.45.2 (SAP advisory). Vendor-listed fixed: 0.45.2.
- Independently reported additional risk: versions 0.53.0–0.55.0 lacked tenant validation in certain SDK paths; 0.55.1+ through 0.58.4 passed the reported tests. SAP had not amended the CVE range to cover those later releases at reporting time.
- Prerequisites: attacker controls an application-provided
tenant_subdomainvalue; affected app uses it to request an OAuth2 token; egress to an attacker-controlled host is permitted. No particular public port or exploit URL has been verified. - Unaffected: applications not using the affected SDK tenant-subdomain token flow, or SDK code paths with validated tenant values. Confirm dependency and call-path details rather than assuming all SAP BTP workloads are affected.
Why this matters
A newly disclosed critical cloud application credential-exfiltration risk with broad downstream authorization impact for tenants using vulnerable SDK flows.
Exploitation Status
No publicly confirmed exploitation as of October 14, 2026 in reviewed SAP/THN reporting. Vendor confirms vulnerability and CVSS 10.0; researcher testing identifies possible later-version validation gaps. No published campaign IOCs or known attacker infrastructure.
What this hunt looks for
Proposed review of Python runtime egress to newly seen domains, proxy token-endpoint requests, tenant-subdomain application messages, SDK package changes, and Python process egress anomalies where those tables and fields are ingested into Sentinel. No customer workspace was queried during preparation.
Required logs
Microsoft Sentinel data sources referenced by these hunts: CommonSecurityLog, DeviceFileEvents, DeviceNetworkEvents, DeviceProcessEvents, Syslog. Availability must be validated per workspace; unsupported tables cannot provide visibility.
KQL Hunting Content
Hunt 1: First pass — Python processes contacting rare external token destinations
Sentinel table: DeviceNetworkEvents. Identify unexpected external connections initiated by Python application runtimes. Without SAP app inventory and expected OAuth hosts, results are hypotheses only.
let known=DeviceNetworkEvents
| where TimeGenerated between (ago(30d)..ago(2d))
| where InitiatingProcessFileName in~ ('python','python3','python.exe','python3.exe','gunicorn','gunicorn.exe','uvicorn','uvicorn.exe')
| where isnotempty(RemoteUrl)
| summarize by DeviceName, RemoteUrl;
DeviceNetworkEvents
| where TimeGenerated >= ago(2d)
| where InitiatingProcessFileName in~ ('python','python3','python.exe','python3.exe','gunicorn','gunicorn.exe','uvicorn','uvicorn.exe')
| where isnotempty(RemoteUrl) and RemotePort in (80,443,8443)
| join kind=leftanti known on DeviceName, RemoteUrl
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteUrl, RemoteIP, RemotePort, ActionType
| order by TimeGenerated desc
Hunt 2: HTTP token endpoint egress in proxy/firewall records
Sentinel table: CommonSecurityLog. Find proxy/WAF records exposing full outbound URL paths. HTTPS TLS inspection or explicit proxy URL logging is required to see token paths.
CommonSecurityLog
| where TimeGenerated >= ago(14d)
| extend Url=tostring(column_ifexists('RequestURL','')), Detail=tostring(column_ifexists('Message',''))
| where Url has_any ('/oauth/token','/oauth2/token','/oauth2/v1/token') or Detail has_any ('/oauth/token','/oauth2/token','/oauth2/v1/token')
| project TimeGenerated, DeviceVendor, DeviceProduct, SourceIP, DestinationIP, DestinationHostName, DestinationPort, DeviceAction, Url, Detail
| order by TimeGenerated desc
Hunt 3: SAP tenant-subdomain or token URL application messages
Sentinel table: Syslog. Search ingested application Syslog only; the relevant SAP BTP application may not emit these strings. Never log or return actual client secrets.
Syslog
| where TimeGenerated >= ago(14d)
| where SyslogMessage has_any ('tenant_subdomain','tenant-subdomain','XsuaaAuthProvider','TokenProvider','sap_cloud_sdk')
| project TimeGenerated, Computer, ProcessName, SeverityLevel, SyslogMessage
| order by TimeGenerated desc
Hunt 4: SAP SDK package installation and version change
Sentinel table: DeviceProcessEvents. Deployment context rather than exploitation evidence. Validate version with package inventory; process command lines are not definitive.
DeviceProcessEvents
| where TimeGenerated >= ago(30d)
| where FileName in~ ('pip','pip3','pip.exe','pip3.exe','python','python3','python.exe','python3.exe','poetry','poetry.exe')
| where ProcessCommandLine has_any ('sap-cloud-sdk','sap_cloud_sdk')
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName
| order by TimeGenerated desc
Hunt 5: SAP SDK library files created or changed
Sentinel table: DeviceFileEvents. Find host file activity in sap_cloud_sdk package paths; not a substitute for dependency manifest or SBOM validation.
DeviceFileEvents
| where TimeGenerated >= ago(30d)
| where FolderPath has 'sap_cloud_sdk' or FileName has 'sap_cloud_sdk'
| project TimeGenerated, DeviceName, InitiatingProcessAccountName, ActionType, FileName, FolderPath, SHA256
| order by TimeGenerated desc
Hunt 6: Python runtime external destination spikes
Sentinel table: DeviceNetworkEvents. Identify unusual egress fan-out from application runtimes that could be consistent with redirected token requests; common SaaS integrations can look similar.
DeviceNetworkEvents
| where TimeGenerated >= ago(14d)
| where InitiatingProcessFileName in~ ('python','python3','python.exe','python3.exe','gunicorn','uvicorn')
| where RemotePort in (80,443,8443) and isnotempty(RemoteIP)
| summarize Connections=count(), UniqueDomains=dcount(RemoteUrl), Domains=make_set(RemoteUrl,15), RemoteIPs=make_set(RemoteIP,15) by DeviceName, InitiatingProcessFileName, bin(TimeGenerated,1h)
| where UniqueDomains >= 10 or Connections >= 100
| order by Connections desc
Hunt 7: Application outbound HTTP requests with unusual tenant values
Sentinel table: CommonSecurityLog. Only meaningful where an application/proxy emits the full request URL including tenant parameter. These strings are generic URL delimiter patterns, not published exploit payloads.
CommonSecurityLog
| where TimeGenerated >= ago(14d)
| extend Url=tostring(column_ifexists('RequestURL',''))
| where Url has 'tenant_subdomain' or Url has 'tenant-subdomain'
| project TimeGenerated, DeviceVendor, DeviceProduct, SourceIP, DestinationIP, DeviceAction, Url
| order by TimeGenerated desc
Detection Notes
Highest signal: outbound OAuth token POST to an unapproved host from an identified SAP SDK application, or logged malformed tenant_subdomain values. Noise: normal Python microservice egress, pip upgrades, token refreshes, shared outbound proxies. Limitations: DeviceNetworkEvents does not reveal HTTPS path or body; CommonSecurityLog RequestURL is often empty for encrypted sessions; Syslog may omit application fields; Python process activity does not establish SAP SDK presence. Do not search for or expose actual client secrets in shared query output. No campaign IOC has been published; exact exploit payloads are not known. Correlate results with app/tenant allowlists and software bill of materials.