Severity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
AC:H reflects the dual prerequisite of a permissive ASGI server and security-sensitive use of request.url before routing; I:L captures host-trust manipulation with no confidentiality or availability impact.
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
Primary rating from NVD.
CVSS VectorNVD
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Lifecycle Timeline
4Blast Radius
ecosystem impact- 3 pypi packages depend on starlette (3 direct, 0 indirect)
Ecosystem-wide dependent count for version 1.3.0.
DescriptionNVD
Summary
In affected versions, the HTTP request path is not validated before being used to reconstruct request.url. Because request.url is rebuilt by concatenating {scheme}://{host}{path} and re-parsing the result, a path that does not begin with / (for example @google.com) moves the authority boundary during re-parsing, so request.url.hostname and request.url.netloc become attacker-controlled. Code that reads request.url.hostname (rather than the Host header or scope) can therefore be misled into trusting an attacker-supplied host.
Details
When a client requests a path that does not start with /:
GET @google.com HTTP/1.1
Host: localhostaffected versions reconstruct the URL as http://localhost@google.com. Per RFC 3986 §3.2.1, the substring before @ in the authority is userinfo, so re-parsing yields username = "localhost" and hostname = "google.com", with an empty path:
request.url == "http://localhost@google.com"
request.url.hostname == "google.com"
request.url.path == ""The root cause is that the path is concatenated directly after the host without a separating /, and without validating that it begins with one. Only the Host header was validated when constructing request.url; the path was not.
This requires an ASGI server that forwards a request-target lacking a leading / into scope["path"].
Impact
Any application running an affected version that uses request.url, request.url.netloc, or request.url.hostname for a security-sensitive decision (host-based authorization, redirect/callback base, SSRF target, cache key, audit log) may be affected, when no fronting proxy or load balancer rejects the malformed request-target first.
Note that this is less exploitable than GHSA-86qp-5c8j-p5mr: there, the poison is carried in the Host header, so the real path still routes to a valid endpoint while request.url.path lies. Here, the poison must be carried in the path itself, and that path (@google.com) does not match any registered route, so routing returns 404 and no endpoint handler runs. The exposure is limited to code that reads request.url before routing - notably middleware - or in 404/exception handlers.
Mitigation
Upgrade to a patched version, which prevents the request path from crossing into the URL authority. The request above instead yields http://localhost/@google.com with request.url.hostname == "localhost".
AnalysisAI
{scheme}://{host}{path} without validating the path prefix, and RFC 3986 §3.2.1 re-parsing then interprets the @ symbol as a userinfo delimiter, shifting hostname authority to the attacker-supplied value. Exploitation is constrained to middleware or 404/exception handlers that act on request.url` before routing, since the malformed path matches no registered route; no active exploitation is confirmed (not in CISA KEV) and no public exploit code beyond the advisory PoC has been identified.
Technical ContextAI
Starlette is a lightweight Python ASGI framework (pkg:pip/starlette) that constructs a Request object from the ASGI scope dictionary. The vulnerable URL reconstruction concatenates {scheme}://{host}{path} from scope fields and then re-parses the result using Python's urllib.parse. When scope['path'] contains a value without a leading / - such as @google.com - the concatenated string becomes http://localhost@google.com. RFC 3986 §3.2.1 defines the @ character as the userinfo delimiter within an authority component, causing the parser to classify localhost as the username and google.com as the hostname. The root cause is CWE-20 (Improper Input Validation): only the Host header was validated during URL construction; the path component was concatenated verbatim. Exploitation additionally depends on the upstream ASGI server (e.g., uvicorn, hypercorn) forwarding a non-slash-prefixed request-target into scope['path'] rather than rejecting or normalizing it. Related advisory GHSA-86qp-5c8j-p5mr describes a prior variant where the poison was carried in the Host header instead.
RemediationAI
Upgrade Starlette to version 1.3.0 or later, which inserts a / separator between the host and path during URL reconstruction, preventing the path from crossing into the URL authority component. The fix version 1.3.0 is confirmed by GitHub Security Advisory GHSA-jp82-jpqv-5vv3 (https://github.com/Kludex/starlette/security/advisories/GHSA-jp82-jpqv-5vv3). If an immediate upgrade is not possible, two compensating controls are available with trade-offs: first, configure the upstream ASGI server or reverse proxy (e.g., nginx return 400 for non-absolute-path request-targets, or uvicorn's request validation settings if available) to reject HTTP requests whose request-target does not begin with / - this eliminates the malformed input before it reaches Starlette, with the trade-off of returning 400 errors to any client sending non-standard request-targets. Second, audit and replace any middleware or error handler code that uses request.url.hostname or request.url.netloc for security decisions, substituting direct access to request.headers['host'] or scope['server'], which are not affected by this path-reparse issue - the trade-off is ongoing manual audit burden.
Same weakness CWE-20 – Improper Input Validation
View allVendor StatusVendor
SUSE
Severity: Low| Product | Status |
|---|---|
| openSUSE Tumbleweed | Fixed |
| SUSE Linux Enterprise Server 16.0 | Affected |
| SUSE Linux Enterprise Server 16.0 | Affected |
| SUSE Linux Enterprise Server 16.1 | Affected |
| SUSE Linux Enterprise Server for SAP applications 16.0 | Affected |
| SUSE Linux Enterprise Server for SAP applications 16.1 | Affected |
| openSUSE Leap 16.0 | Affected |
| openSUSE Leap 15.6 | Affected |
Share
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-38318
GHSA-jp82-jpqv-5vv3