SAP CAP CVE-2026-76969 – Unauthenticated Multitenant Credential Disclosure

Threat Overview

SAP’s September 8, 2026 Security Patch Day disclosed CVE-2026-76969, a critical CVSS 9.4 vulnerability in the `@sap/cds-mtxs` NPM library used by multitenant SAP Cloud Application Programming Model (CAP) applications with extensibility enabled. SAP states that the library does not perform sufficient checks on certain functionality. An unauthenticated remote attacker can send crafted requests to obtain sensitive credentials and then abuse those credentials to replace or delete tenant data. SAP rates the confidentiality impact as partial and the integrity and availability impact as high.

The vulnerability is configuration-dependent: CAP applications must use the affected multitenancy-extension library and have extensibility enabled. SAP’s Patch Day page lists affected library versions as <=1.18.3, <=2.7.6, <=3.9.6, and <=4.0.2. No public exploit or confirmed in-the-wild exploitation was identified in the sources reviewed on September 8, 2026.

References

Impacted Systems

Vendor/product: SAP Cloud Application Programming Model (CAP), Node.js applications using NPM package `@sap/cds-mtxs`. Deployment model: multitenant CAP applications with extensibility enabled, including Internet-facing applications where the vulnerable functionality is reachable. Affected versions listed by SAP: `@sap/cds-mtxs` <=1.18.3, <=2.7.6, <=3.9.6, and <=4.0.2. Attack prerequisite: network reachability to an affected multitenant CAP application; no authentication or user interaction is required. Potential impact: disclosure of sensitive credentials followed by unauthorized replacement or deletion of tenant data. Exact request path, exploit payload, and fixed package versions were not publicly available in the sources used for this report; customers should follow SAP Security Note 3798315 for the authoritative remediation package/version.

Why this matters

This vulnerability crosses application, credential, and tenant boundaries. A single exposed multitenant CAP application may serve multiple business tenants, so credential disclosure followed by destructive tenant-data operations could produce broad business impact without first requiring a valid account.

Criticality: Critical

Exploitation Status

No confirmed exploitation in the wild was identified in the sources reviewed as of September 8, 2026. No public PoC or weaponized exploit was identified. This is a newly disclosed, unauthenticated, network-reachable critical vulnerability and should be treated as a high-priority exposure and patching issue without overstating exploitation status.

What this hunt looks for

Available Microsoft Sentinel telemetry can be reviewed for unusual unauthenticated requests to identified CAP applications, anomalous HTTP methods and request volumes, spikes in 4xx/5xx responses, new or unusual outbound connections from CAP workloads, unexpected credential use in downstream cloud or database telemetry, and destructive application/database operations where WAF, reverse-proxy, application, cloud, or database logs are ingested. No CVE-specific request signature is asserted because SAP has not publicly disclosed the exploit path or payload in the sources used.

Required logs

  • CommonSecurityLog from WAF, reverse proxy, or firewall telemetry protecting the CAP application
  • Microsoft Defender XDR / Defender for Endpoint DeviceNetworkEvents and DeviceProcessEvents where host telemetry exists
  • AzureActivity and/or AWSCloudTrail when downstream cloud activity is relevant and ingested

First Pass – New External Sources Reaching CAP Applications

let CAPDestinations = dynamic(["REPLACE_WITH_CAP_PUBLIC_IP_OR_BACKEND_IP"]);
let Baseline = CommonSecurityLog
| where TimeGenerated between (ago(30d) .. ago(2d))
| where DestinationIP in (CAPDestinations)
| summarize by SourceIP;
CommonSecurityLog
| where TimeGenerated > ago(2d)
| where DestinationIP in (CAPDestinations)
| where SourceIP !in (Baseline)
| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Requests=count(), Methods=make_set(RequestMethod,20), URLs=make_set(RequestURL,50), Actions=make_set(DeviceAction,20) by SourceIP, DestinationIP
| order by Requests desc

CAP Application HTTP Error and Anomaly Spike

let CAPDestinations = dynamic(["REPLACE_WITH_CAP_PUBLIC_IP_OR_BACKEND_IP"]);
CommonSecurityLog
| where TimeGenerated > ago(14d)
| where DestinationIP in (CAPDestinations)
| extend Raw=strcat(Message," ",AdditionalExtensions)
| where Raw has_any (" 400 "," 401 "," 403 "," 404 "," 500 "," 502 "," 503 ","error","exception","invalid")
| summarize Events=count(), Sources=dcount(SourceIP), URLs=make_set(RequestURL,50) by DestinationIP, bin(TimeGenerated,15m)
| where Events >= 20
| order by TimeGenerated desc

Unusual HTTP Methods Against CAP Applications

let CAPDestinations = dynamic(["REPLACE_WITH_CAP_PUBLIC_IP_OR_BACKEND_IP"]);
CommonSecurityLog
| where TimeGenerated > ago(14d)
| where DestinationIP in (CAPDestinations)
| where RequestMethod !in~ ("GET","POST","OPTIONS","HEAD")
| project TimeGenerated, SourceIP, DestinationIP, RequestMethod, RequestURL, DeviceAction, Message
| order by TimeGenerated desc

Rare URLs or API Paths Against CAP Applications

let CAPDestinations = dynamic(["REPLACE_WITH_CAP_PUBLIC_IP_OR_BACKEND_IP"]);
let Baseline = CommonSecurityLog
| where TimeGenerated between (ago(30d) .. ago(2d))
| where DestinationIP in (CAPDestinations)
| summarize by RequestURL;
CommonSecurityLog
| where TimeGenerated > ago(2d)
| where DestinationIP in (CAPDestinations)
| where RequestURL !in (Baseline)
| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Requests=count(), Sources=make_set(SourceIP,20), Methods=make_set(RequestMethod,20) by DestinationIP, RequestURL
| order by Requests desc

New Outbound Destinations From CAP Application Hosts

let CAPHosts = dynamic(["REPLACE_WITH_CAP_HOSTNAME"]);
let Baseline = DeviceNetworkEvents
| where TimeGenerated between (ago(30d) .. ago(2d))
| where DeviceName in~ (CAPHosts)
| summarize by RemoteUrl, RemoteIP;
DeviceNetworkEvents
| where TimeGenerated > ago(2d)
| where DeviceName in~ (CAPHosts)
| where (RemoteUrl, RemoteIP) !in (Baseline)
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteUrl, RemoteIP, RemotePort
| order by TimeGenerated desc

CAP Node.js Process Spawning Shells or Network Utilities

let CAPHosts = dynamic(["REPLACE_WITH_CAP_HOSTNAME"]);
DeviceProcessEvents
| where TimeGenerated > ago(14d)
| where DeviceName in~ (CAPHosts)
| where InitiatingProcessFileName in~ ("node","node.exe")
| where FileName in~ ("sh","bash","cmd.exe","powershell.exe","pwsh.exe","curl","wget","nc","ncat")
| project TimeGenerated, DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine, SHA256
| order by TimeGenerated desc

Azure Activity Changes Near a Suspected CAP Event

AzureActivity
| where TimeGenerated > ago(14d)
| where ActivityStatusValue =~ "Success"
| where OperationNameValue has_any ("write","delete","action")
| project TimeGenerated, Caller, CallerIpAddress, OperationNameValue, ResourceGroup, ResourceId, ActivityStatusValue, CorrelationId
| order by TimeGenerated desc

AWS CloudTrail Destructive or Credential-Relevant Activity

AWSCloudTrail
| where TimeGenerated > ago(14d)
| extend Event=tostring(EventName), Arn=tostring(UserIdentityArn), Src=tostring(SourceIpAddress)
| where Event has_any ("Delete","Put","Update","CreateAccessKey","GetSecretValue","AssumeRole")
| project TimeGenerated, Event, Arn, Src, RequestParameters, ErrorCode, ErrorMessage
| order by TimeGenerated desc

Detection Notes

There is no publicly disclosed CVE-specific request endpoint or payload in the sources used, so HTTP hunts intentionally focus on behavior and change from baseline rather than fabricated signatures. WAF and reverse-proxy schemas vary; CommonSecurityLog field population should be validated before relying on status-code or URL logic. Endpoint hunts only apply when the CAP workload is visible through Defender/XDR endpoint telemetry; many cloud-native CAP deployments may not expose host-level process telemetry. Downstream credential abuse may appear in Azure, AWS, database, or application audit logs only if those sources are ingested into Sentinel.