SAP Security Note 3765948 | CVSS 3.0 base score 9.9 (CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H) | Component MFG-MII | HotNews | SAP Security Patch Day, 11 August 2026
Classes: CWE-918 (server-side request forgery), CWE-94 (code injection)
At a glance
CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:HSummary
The SAP MII Illuminator query servlet accepted three request parameters (InlineTransform, CalculationTransform and StyleSheet) whose value is a URL from which the server fetches an XSL stylesheet. Before the August 2026 patch nothing validated the destination of that URL, so an authenticated user holding ordinary query-execution rights could make the NetWeaver AS Java host issue arbitrary HTTP requests and could have the fetched response body compiled and executed as an XSLT stylesheet inside the server process. A second, cruder endpoint, IllumXSLTServlet, exposed a comparable pattern through raw URL and Transform parameters and is corrected separately as CVE-2026-44758 under SAP Note 3758900.
The patch introduces a host allow-list gate in the Illuminator code path and removes the IllumXSLTServlet endpoint entirely. The allow-list gate is disabled by default. Installing the patch without also switching on the new SecureTransformer system property leaves the Illuminator behaviour unchanged.
Affected products and versions
SAP Manufacturing Integration and Intelligence. The comparison behind this advisory used two software component archives per side:
| Software component | Archive | Vulnerable sample | Fixed sample |
|---|---|---|---|
| XMII (MII runtime) | XMII02 |
15.5 SP2 patch 0, MII1552V.05080417, keycounter 1000.15.5.2.0.20250508041720, keylocation MAIN_MII1552V_C |
15.5 SP2 patch 13, MII1552P.07310816, keycounter 1000.15.5.2.13.20260731081708, keylocation MAIN_MII1552P_C |
| MII_ADMIN (administration UI) | MIIADMIN02 |
15.5 SP2 patch 0, MII1552V.05080415, keycounter 1000.15.5.2.0.20250508041519 |
15.5 SP2 patch 6, MII1552P.06231619, keycounter 1000.15.5.2.6.20260623161932 |
Only these two levels were compared; other MII releases were not examined. SAP Note 3765948 is the authoritative list of affected releases and required patch levels.
Technical detail
Entry point
com/sap/xmii/servlet/Illuminator.java is mapped at /XMII/Illuminator/* and sits behind the XMII Filter (com.sap.xmii.system.SecurityFilter). Its service() method performs no authorisation of its own; it calls ServiceManager.createData() and ServiceManager.run() (lines 93 and 96, identical pre- and post-patch). Authorisation happens inside ServiceManager.checkPermissions(), which requires a resolved user and a permission on the named service:
// com/sap/xmii/Illuminator/services/ServiceManager.java, lines 95-98
if (!SystemPermissionManager.hasPermission(serviceName, user)) {
ServiceManager.LOG.error("Invalid permission to access service " + serviceName);
throw new LHException("UNAUTHORIZED_SERVICE_ACCESS", serviceName);
}
This is not an unauthenticated vulnerability, which matches SAP’s PR:L metric. It is reachable by any account that can already run Illuminator queries, in most landscapes a broad population.
Input under attacker control
com/sap/xmii/Illuminator/tools/builder/XMLBuilder.java is the builder selected for the XML output modes. Its private configureTransformers() method (declared at line 459 pre-patch, 460 post-patch) reads three parameters straight from the request:
// out_old/.../XMLBuilder.java, lines 471-473
this.sInlineTransform = WebInfo.checkURL(this.data.getRequest(), this.data.getParameters().getParameter("InlineTransform"));
this.sCalculationTransform = WebInfo.checkURL(this.data.getRequest(), this.data.getParameters().getParameter("CalculationTransform"));
this.sFinalTransform = WebInfo.checkURL(this.data.getRequest(), this.data.getParameters().getParameter("StyleSheet"));
configureTransformers() runs from the XMLBuilder constructor (line 119) and from configureTransformForQueryEngine() (line 664), which is in turn called from the BLS Illuminator query action, from MIIClient and from the remote PCo helpers. The same three parameter names therefore also reach this code when a query template is executed inside a business logic transaction rather than by a live HTTP request.
The control that was missing
The only processing applied was WebInfo.checkURL(), which is byte-identical in both trees:
// com/sap/xmii/Illuminator/common/WebInfo.java, lines 29-38
if (url.substring(0, 9).equalsIgnoreCase("server://")) { return getServerURL(request) + "/" + url.substring(9); }
if (url.substring(0, 6).equalsIgnoreCase("web://")) { return getServerURL(request) + "/" + "XMII" + "/" + "CM" + "/" + url.substring(6); }
if (url.startsWith("/XMII/")) { return getServerURL(request) + url; }
return url;
It rewrites three local-reference forms into absolute URLs and returns everything else unchanged: no scheme restriction, no host allow-list, no check for internal, loopback or metadata addresses. The method is unchanged by the patch, confirming it was never a security control.
Path to the sink
setFinalTransform() (and its inline and calculation siblings) dispatch on the value:
// out_new/.../XMLBuilder.java, lines 616-625
final String url = this.sFinalTransform.toUpperCase(Locale.ENGLISH);
if (url.startsWith("XACUTE://")) { this.finalTransformer = this.createXacuteTransformer(...); }
else if (url.startsWith("JAVA://")) { this.finalTransformer = this.createJavaTransformer(this.sFinalTransform); }
else { this.finalTransformer = new XSLTransformer(tFactory, this.sFinalTransform, this.data); }
The default branch reaches XSLTransformer, which fetches the URL server-side and compiles the response as a stylesheet:
// com/sap/xmii/Illuminator/tools/builder/XSLTransformer.java, lines 56, 65, 69 (old)
xsldoc = XMLHandler.getDocument(url, 0, "", "", cookies);
...
this.transformer = tFactory.newTransformer(xsl);
...
this.transformer.setURIResolver(new XSLEntityResolver(cookies));
XMLHandler.getDocument() opens an HTTPConnection for any http:// or https:// URL, forwarding the caller’s session cookies (XMLHandler.java:294-329, cookie header set at :309), and parses the response. That is the server-side request forgery. Because the fetched bytes are then handed to newTransformer() and executed, an attacker who also controls the responding host controls the stylesheet, which is the code-injection consequence.
The JAVA:// branch is a second sink reachable from the same parameters. createJavaTransformer() (lines 556-564) treats the remainder of the string as a class name, reflectively instantiates it as a javax.xml.transform.Transformer, and copies every request parameter onto it. That is constrained to classes already on the server classpath, but it is instantiation of an attacker-named class from an HTTP parameter.
Existing XML hardening does not help here, for a reason independent of how it is configured: the stylesheet is retrieved by SAP’s own HTTP client before the XSLT engine is involved at all, and a custom URIResolver installed on the transformer supersedes the engine’s own resolution. accessExternalDTD and accessExternalStylesheet are not set on the MII transformer factories in either tree.
Second entry point
com/sap/xmii/servlet/IllumXSLTServlet.java (133 lines pre-patch) read URL, XMLSource, Transform and XSLSource directly from the request (lines 60-63), fetched the URL and Transform values with XMLHandler.getDocument() (lines 75 and 87), compiled the result and streamed the transformation to the response (lines 94 and 113). It was gated only by SystemPermissionManager.hasPermission("IllumXSLTServlet", user) at line 54. That endpoint is the subject of CVE-2026-44758 and is described in a separate advisory; the removal is noted here because it is part of the same shipped change.
What the patch changes
1. A gate in front of the three transform parameters. XMLBuilder gains sanitizeTransformParams() (new lines 514-549), called at lines 475-477 before WebInfo.checkURL(). It exempts the same local forms (server://, web://, plus db://, /XMII/, and any URL beginning with this server’s own URL), then parses the value as a java.net.URI, rejects embedded credentials, and passes uri.getHost() to a new validateHost():
// out_new/.../XMLBuilder.java, lines 680-698
public void validateHost(final String hostName) throws Exception {
boolean validHost = false;
if (SystemPropertyManager.getSystemProperties().getSecureTransformer()) {
final String allowedHosts = SystemPropertyManager.getSystemProperties().getAllowedUrls();
...
if (!validHost) { throw new LHException("Blocking Transformation; host is invalid"); }
}
}
LHException extends RuntimeException (LHException.java:12), so a rejection aborts the builder before any fetch is attempted. These two methods and one java.net.URI import are the entire diff of the file.
2. Two new system properties. SystemProperties.java gains SECURE_TRANSFORMER = "SecureTransformer" and ALLOWED_URLS = "AllowedList" (lines 106-107) with getters getSecureTransformer() at line 326 and getAllowedUrls() at line 330. Both are absent from the pre-patch file, and those four additions are the entire diff of the file. getSecureTransformer() routes through the pre-existing getBooleanProperty() (lines 227-234), which returns false and logs a warning when the property is unset. The gate is therefore off until an administrator turns it on.
3. The IllumXSLTServlet endpoint is removed, not repaired. Its service() body is empty in the patched class, every transform-related import is gone, and in sap.com~xapps~xmii~web/WEB-INF/web.xml the servlet declaration, its /IllumXSLTServlet mapping and its security-filter mapping are all commented out.
4. Administration UI. IMessageSysConfigComp in MII_ADMIN gains exactly three labels, XLBL_TRANSFORMER_SETTINGS, XLBL_SECURE_TRANSFORMER and XLBL_ALLOWEDLIST (lines 247-249), exposing a new Transformer Settings section on the System Configuration screen. This is the only change in that file.
Verification for defenders
- Confirm the component level. In NetWeaver Administrator or the MII system information screen, check that software component
XMIIis at the patch level named in SAP Note 3765948 (patch 13 or later on the 15.5 SP2 line), andMII_ADMINcorrespondingly (patch 6 or later on that line).
- Confirm the removed endpoint. Request
/XMII/IllumXSLTServleton the MII host with no parameters. On a patched system the servlet is no longer declared or mapped in the web application, so the container answers with a not-found response. On an unpatched system it is a live servlet. This is the cheapest positive version marker.
- Find the new configuration. In the MII administration menu open System Management, then System Administration, then System Configuration, and look for a Transformer Settings section containing Secure Transformer and Allowed List. If that section is absent, the MII_ADMIN component has not been patched.
- Switch Secure Transformer on. This is the step that actually closes the vulnerability for the Illuminator path. Until it is on,
validateHost()returns immediately and the pre-patch behaviour is preserved exactly. Confirm afterwards that the application log no longer emitsSystemProperty SecureTransformer was null or empty, defaulting to false; that message is proof the toggle is still unset.
- Populate the Allowed List correctly. Enter a comma-separated list of bare host names only for the hosts that legitimately serve XSL stylesheets to this system. Matching is an exact, case-insensitive comparison against the host component of the requested URL. Do not use a wildcard. Do not use scheme-qualified entries such as a full URL, and do not include a port or a path. Leaving the list empty while Secure Transformer is on causes every non-local transform to be rejected.
- Regression-check known-good templates. Templates referencing a stylesheet by the local forms
server://,web://,db://,/XMII/…or by this server’s own URL are exempt and keep working. Templates naming an external host fail withBlocking Transformation; host is invalidin the application log until that host is allow-listed. Seeing that message on a template known to be legitimate confirms the control is live, without introducing untrusted input.
Detection
MII logs every server-side document fetch at INFO level, in both the vulnerable and the patched code:
// com/sap/lhcommon/xml/XMLHandler.java, line 284 (old) / 312 (new)
XMLHandler.LOG.info("sURL: " + sURL + " nTimeout: " + nTimeout);
Retained MII application logs are therefore the primary evidence. Review sURL: entries for destinations that are neither the MII host nor a known content server, with attention to internal management, loopback and link-local addresses. Also search for Unable to read XSL document [<url>] from XSLTransformer and Unable to resolve [<href>,<base>] from XSLEntityResolver, both of which record the URL on failure; at DEBUG level XMLBuilder logs Final transformer is <url>.
In web dispatcher, ICM or reverse-proxy access logs, look for requests to /XMII/Illuminator whose InlineTransform, CalculationTransform or StyleSheet values name a host other than the MII server or an approved content host, and for any request to /XMII/IllumXSLTServlet. Correlate with outbound connections from the AS Java host. The outbound fetch forwards the calling user’s session cookies, so activity may be attributable to a specific MII account.
Absence of these lines is weak evidence: MII logging levels and retention vary, and a fetch that never completed may leave only a failure message.
References
- SAP Security Note 3765948: https://me.sap.com/notes/3765948
- CVE-2026-44772
- Related issue in the same patch, tracked separately: SAP Security Note 3758900, CVE-2026-44758, covering the
IllumXSLTServletendpoint removed by this same change: https://me.sap.com/notes/3758900 - SAP Security Patch Day, August 2026
The vulnerability was reported to SAP by an external researcher, credited in SAP Note 3765948. This advisory documents the vulnerability and the shipped fix as they appear in the affected software components.
This is one of six SAP MII vulnerabilities corrected on the August 2026 patch day. The full cycle, including the other 19 notes, is covered in the SAP Security Patch Day August 2026 advisory.
Custom code carries the same defect classes
Missing authorization checks, injection into dynamically assembled calls and unvalidated file paths are the recurring findings in customer ABAP as well as in vendor code. The RedRays ABAP Code Scanner reads your own objects and reports them at the line that causes them.
This advisory summarises publicly relevant facts about an SAP Security Note that SAP has already released, together with an analysis of the shipped correction. It is not a substitute for the note itself; customers should always refer to the original note in the SAP Support Portal for authoritative guidance on affected releases and required patch levels. No exploit code is published. RedRays is an independent SAP security vendor and is not affiliated with SAP SE.
