A reverse proxy that can't agree with its backend on where one HTTP request ends and the next begins
SAP Approuter is the Node.js-based reverse proxy fronting apps deployed on SAP BTP (Business Technology Platform) — it terminates external traffic, handles OAuth/UAA login flow, and forwards requests to backing microservices. CVE-2026-27690 is a classic CL.TE / TE.CL desync (CWE-444) where Approuter and its upstream disagree on request boundaries. An unauthenticated attacker sends a crafted request with conflicting Content-Length / Transfer-Encoding framing; the smuggled payload gets prepended to the *next* legitimate user's request on the same keep-alive connection, so the attacker can steal that user's response (session cookies, JWTs, personal data) or poison a shared cache. Affected: Approuter versions < 20.10.0; fix is 20.10.0.
The vendor 9.1 (AV:N/AC:L/PR:N/UI:N/C:H/I:N/A:H) is defensible but slightly overheated. Smuggling here does not give RCE, does not give write-side integrity impact (I:N is honest), and the confidentiality impact is bounded by whatever passes through Approuter — session tokens and app responses, not the SAP database directly. It's a genuine unauth internet-reachable primitive against a component that is *deliberately* internet-exposed, which is why we hold it at HIGH rather than downgrading to MEDIUM.
4 steps from start to impact.
Enumerate Approuter endpoint and fingerprint version
*.cfapps.<region>.hana.ondemand.com or a custom domain CNAMEd to it. Response headers (x-vcap-request-id, x-powered-by), the /login/callback OAuth flow, and error pages fingerprint Approuter. Version pinning via timing/behaviour differences on chunked requests confirms < 20.10.0.- Approuter instance reachable from the internet
- Version < 20.10.0
- Many BTP tenants restrict Approuter to corporate IP ranges or SAP Cloud Connector overlays
- WAF in front (SAP Web Dispatcher, CloudFront, F5) may normalize framing
manifest.yml and buildpack metadata.Probe for CL.TE / TE.CL desync
smuggler.py (defparam), Burp Repeater, or http-request-smuggler (Burp BApp) to send probe requests with conflicting Content-Length and Transfer-Encoding: chunked headers. Differential response timing (500ms hang vs immediate reply) confirms one endpoint honours CL and the other TE. Node.js HTTP parser quirks (obs-fold, CR-only line terminators, Transfer-Encoding: chunked\r\nX) are the usual triggers.- HTTP/1.1 keep-alive between Approuter and upstream
- No strict framing normalizer between attacker and Approuter
- HTTP/2 downgrade to HTTP/1.1 upstream is required — pure HTTP/2 end-to-end kills the class
- Front-end CDN often rewrites framing
Weaponize smuggled request against a victim session
/attacker-collector or reflected in a stored resource). Tools: HTTP Request Smuggler for auto-poisoning, Turbo Intruder for concurrent smuggling. Alternatively poison Approuter's response cache to serve attacker JS to the next N users.- Shared upstream connection pool
- Active concurrent traffic (victim users)
- Approuter's default per-tenant isolation limits poison blast radius
- Session-bound routing (sticky sessions) narrows victim pool
x-vcap-request-id.Replay captured session or pivot into BTP app
- Token not bound to source IP or TLS channel
- Victim had privileged role
- xsuaa token lifetime is short (default 12h)
- Some tenants enforce mTLS or IP allowlisting on tokens
The supporting signals.
| In-the-wild exploitation | None observed as of 2026-07-14 disclosure; no vendor or Onapsis IOC advisory. |
|---|---|
| Public PoC | No CVE-specific PoC published yet. Generic tooling (smuggler.py by defparam, Burp HTTP Request Smuggler by Albinowax) trivially adapts. |
| EPSS | Not yet scored (published today); expect <1% initial, rising if PoC lands. |
| KEV status | Not listed by CISA KEV. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H — network, no auth, no UI, high confidentiality + availability, no integrity impact (bounded to response theft / DoS). |
| Affected versions | SAP Approuter < 20.10.0 (Node.js @sap/approuter npm package). |
| Fixed version | 20.10.0 — install via npm install @sap/approuter@20.10.0 and redeploy BTP app. |
| Exposure population | SAP BTP hosts tens of thousands of Approuter frontends; most are internet-facing by design. Shodan/Censys BTP fingerprint counts run in the low six figures. |
| Disclosure | 2026-07-14 — SAP Security Patch Day July 2026, one of 16 notes + 1 GHSA. |
| Reported by | Credited via SAP Security Note; researcher not yet public in advisory text. |
noisgate verdict.
Held at HIGH — the single decisive factor is role blast radius: Approuter is the internet-facing identity broker for BTP apps, so a smuggling primitive here directly steals user sessions and OAuth tokens at scale. The half-point trim from 9.1 reflects that impact is bounded to what transits the proxy (I:N, no RCE) rather than full backend takeover.
Why this verdict
- Role multiplier — Approuter IS the identity broker. For BTP-hosted apps, Approuter terminates external TLS, runs the OAuth handshake with xsuaa, and injects the JWT into upstream calls. Smuggling here = session theft on the auth boundary itself. Chain succeeds → tenant-wide session hijack. Floor: HIGH.
- Unauth, network-reachable, low complexity — no prerequisite compromise stage. Attacker needs only a TCP path to the Approuter, and BTP apps are internet-facing by product design (unlike, say, an internal ESXi). Baseline severity is preserved, not downgraded, for exposure.
- Integrity is bounded (I:N). No RCE, no code write, no privilege escalation into SAP kernel. Blast radius is limited to sessions and cached responses that flow through the specific vulnerable Approuter instance — not fleet-scale SAP compromise. This is why we sit at HIGH, not CRITICAL.
- Modern mitigations partially blunt the class. BTP tenants fronted by SAP Web Dispatcher, CloudFront, or Cloudflare with strict HTTP/1.1 normalization will drop conflicting-framing requests before they reach Approuter. HTTP/2 end-to-end (rare but growing) eliminates the vector.
- No KEV, no in-the-wild, no PoC at disclosure — pulls us off CRITICAL to HIGH pending exploitation evidence. If a working PoC lands (expect within 30 days for a class this well-tooled), re-rate to 9.0+.
Why not higher?
CRITICAL requires either integrity/RCE impact or active exploitation of a canonical fleet-owning component. This is C:H/I:N — the attacker reads and disrupts but does not write or execute. No KEV listing, no public PoC on day one, and blast radius is scoped to the individual Approuter's connection pool, not the SAP application server or HANA database behind it.
Why not lower?
MEDIUM is off the table: unauthenticated, network-reachable, low-complexity attack against an internet-facing identity broker that handles OAuth tokens for BTP customer tenants. The role multiplier (Approuter = auth edge) enforces a HIGH floor even without in-the-wild evidence.
What to do — in priority order.
- Upgrade
@sap/approuterto 20.10.0 and redeploy affected BTP apps — The only complete fix.cf pushor Kyma redeploy after bumpingpackage.json. Deploy within 30 days per noisgate HIGH mitigation SLA; complete fleet rollout within 180 days per remediation SLA. - Front Approuter with a strict HTTP/1.1-normalizing proxy — Place SAP Web Dispatcher, Cloudflare, or an AWS ALB with
routing.http.drop_invalid_header_fields.enabled=truein front. Reject requests containing bothContent-LengthandTransfer-Encoding, or with obs-fold / CR-only line endings. Deploy within 30 days. - Enable HTTP/2 end-to-end where the upstream supports it — HTTP/2 uses length-prefixed frames — the CL/TE ambiguity does not exist. Kills the class entirely for upgraded connections.
- Shorten JWT / xsuaa token lifetimes and enforce IP-bound tokens — Reduces the value of any smuggled session capture. Set
token-validityto ≤ 3600s and enablex-forwarded-for-bound token issuance in xsuaa config. - Instrument Approuter access logs for smuggling signatures — Alert on requests with both CL and TE headers, on 400/408 anomaly spikes, and on duplicate
x-vcap-request-id. Push to your SIEM this week.
- WAF signature rules alone — request smuggling probes are legal HTTP; only *strict-normalization* modes catch them, not typical OWASP CRS signatures.
- MFA on the app — MFA happens *inside* the session that gets hijacked; smuggling steals the post-auth cookie/JWT, so MFA is already satisfied.
- Rate limiting — a single probe is enough to confirm the desync; volumetric controls don't help.
- Network segmentation of the SAP backend — Approuter is the *front door*, deliberately reachable. Segmenting HANA or S/4 does not protect the sessions passing through the proxy.
Crowdsourced verification payload.
Run on any host that has the BTP CF CLI installed and is logged into the target org/space. Invoke as ./check-approuter.sh <app-name> — needs read (SpaceDeveloper or higher) on the target space. Emits VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env bash
# noisgate: CVE-2026-27690 SAP Approuter version check
# Usage: ./check-approuter.sh <cf-app-name>
set -u
APP="${1:-}"
FIXED="20.10.0"
if [[ -z "$APP" ]]; then
echo "usage: $0 <cf-app-name>" >&2
exit 2
fi
if ! command -v cf >/dev/null 2>&1; then
echo "UNKNOWN: cf CLI not installed" >&2
exit 3
fi
# Pull the running package.json from the container
VER=$(cf ssh "$APP" -c 'cat /home/vcap/app/package.json 2>/dev/null | \
grep -oE "\"@sap/approuter\"\s*:\s*\"[^\"]+\"" | \
grep -oE "[0-9]+\.[0-9]+\.[0-9]+"' 2>/dev/null | head -n1)
if [[ -z "$VER" ]]; then
# Fallback: check node_modules
VER=$(cf ssh "$APP" -c 'cat /home/vcap/app/node_modules/@sap/approuter/package.json 2>/dev/null | \
grep -oE "\"version\"\s*:\s*\"[^\"]+\"" | \
grep -oE "[0-9]+\.[0-9]+\.[0-9]+"' 2>/dev/null | head -n1)
fi
if [[ -z "$VER" ]]; then
echo "UNKNOWN: could not read @sap/approuter version from $APP"
exit 3
fi
# semver compare
lowest=$(printf '%s\n%s\n' "$VER" "$FIXED" | sort -V | head -n1)
if [[ "$VER" == "$FIXED" || "$lowest" == "$FIXED" ]]; then
echo "PATCHED: $APP running @sap/approuter $VER (>= $FIXED)"
exit 0
else
echo "VULNERABLE: $APP running @sap/approuter $VER (< $FIXED)"
exit 1
fi
If you remember one thing.
@sap/approuter and pin the version — anything < 20.10.0 is in scope. Per the noisgate mitigation SLA for HIGH, deploy compensating controls (front-end HTTP/1.1 strict normalization, shorten xsuaa token TTLs, log-based smuggling detection) within 30 days; per the noisgate remediation SLA, complete the npm install @sap/[email protected] + cf push upgrade across the fleet within 180 days. If CISA adds this to KEV or a working PoC lands publicly (watch defparam/GitHub and Burp community), collapse both deadlines to *patch within hours* — this class weaponizes fast once someone publishes the exact CL/TE trigger for Approuter's Node parser.Sources
- SAP Security Patch Day — July 2026
- SecurityBridge Cloud — SAP Security Notes 2026
- Cryptika — SAP Security Update July 2026
- entplexit — SAP Security News 07/2026
- Onapsis — HTTP Request Smuggling in SAP Web Dispatcher (class background)
- PortSwigger — HTTP Request Smuggling research
- SAP Approuter npm package
- CWE-444 — Inconsistent Interpretation of HTTP Requests
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.