Dev.to Security 🔐 Cybersecurity 👁 0 📖 5 min read

CVE-2026-48710 (BadHost): How a Malformed Host Header Bypasses Starlette Path Authorization

CVE-2026-48710 (BadHost): How a Malformed Host Header Bypasses Starlette Path Authorization Vulnerability overview CVE-2026-48710, tracked publicly as BadHost and catalogued by X41 D-Sec as X41-2026-002, is

CVE-2026-48710 (BadHost): How a Malformed Host Header Bypasses Starlette Path Authorization

Vulnerability overview

CVE-2026-48710, tracked publicly as BadHost and catalogued by X41 D-Sec as X41-2026-002, is an authentication bypass in the Starlette ASGI framework. The flaw is CWE-444, inconsistent interpretation of HTTP requests. Starlette maintainers published a GitHub security advisory with a CVSS v3.1 base score of 6.5 (Medium), vector AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N. X41 D-Sec rated the practical risk higher, at 7.0, and argued that the score understates impact in AI tooling deployments. On 2026-09-02 CISA added CVE-2026-48710 to its Known Exploited Vulnerabilities catalog, citing evidence of active exploitation.

Mechanism and exploitation conditions

Starlette reconstructs request.url from the ASGI scope dictionary. Before version 1.0.1, that reconstruction concatenated the client-supplied Host header with the request path and re-parsed the result as a URL, without validating the Host value against RFC 9112 or RFC 3986. When the Host header contains URI delimiters such as /, ?, #, @, backslash, or a space, the re-parsed URL shifts the path boundary.
The result is a disagreement between two path sources inside one request:

  • The router dispatches on scope["path"], the raw request-target path.
  • Middleware that reads request.url.path sees the value produced by the polluted reconstruction. A request for /admin sent with Host: example.com/public?x= is routed to /admin, but request.url.path evaluates to /public. Any authorization middleware that decides on request.url.path — a path-prefix allowlist, for example — evaluates the attacker-influenced value while the router serves the real, protected endpoint. Exploitation requires a specific combination, not merely the presence of Starlette:
  • The application must rely on request.url or request.url.path for a security decision, most commonly a path-prefix allowlist or a public-path bypass list.
  • No reverse proxy, CDN, or API gateway in front of the application may already reject or normalize malformed Host values.
  • The application server must be reachable with an attacker-controlled Host header. Endpoints protected by FastAPI Depends() or Security() dependencies, or by business-layer permission checks, are not bypassed by path pollution alone, because those checks bind to the endpoint rather than to a reconstructed URL. ## Impact Successful exploitation yields unauthenticated access to endpoints the application intended to protect. X41 D-Sec demonstrated the transition from a 403 Forbidden response to 200 OK after adding a single character to the Host header. Because the bypass is a precondition rather than a terminal action, severity depends on what the reachable endpoint does. X41 D-Sec found multiple open-source projects whose security checks depend on the reconstructed URL, and warned that the flaw can chain from authentication bypass into server-side request forgery and, in some deployments, remote code execution. The LiteLLM case shows the chain concretely. Horizon3.ai reported that CVE-2026-48710 removes the authentication requirement from CVE-2026-42271, a command injection in LiteLLM's MCP test endpoints. Chained, the two flaws permit unauthenticated remote code execution on the LiteLLM host, exposing model provider credentials, proxy-stored API keys, and connected AI infrastructure. Horizon3.ai assessed the combined chain at CVSS 10.0. ## Affected products and scope
  • Starlette: versions from 0.8.3 up to and including 1.0.0 are affected. Version 1.0.1 is the fix.
  • Downstream frameworks: FastAPI depends on Starlette, so applications built on FastAPI inherit the flaw unless the underlying Starlette version is patched. vLLM, Text Generation Inference, LiteLLM, and many MCP server implementations sit on this stack.
  • LiteLLM: versions 1.74.2 through 1.83.6 ship the vulnerable MCP debug endpoints; 1.83.7 fixes the command injection but not the framework-level bypass. Version 1.84.0 or later addresses both. Scope follows code behaviour, not installation. An application that never imports Starlette directly can still be affected through a transitive dependency, and GitHub lists more than 400,000 dependent projects. Conversely, a Starlette application that never makes a security decision on request.url.path is not exploitable through this specific mechanism. ## Exposure context A ZoomEye query for http.body="Starlette" returned 1,249 matching assets at the time of writing. A narrower query combining http.header.server="uvicorn" with http.body="Starlette" returned 437 assets, and title="Starlette" returned 252. A CVE-specific query for vul.cve="CVE-2026-48710" returned 0, which reflects indexing coverage rather than absence of affected systems. These counts describe assets whose responses contain Starlette-related strings; they do not confirm that any specific host runs an affected version or exposes a bypassable authorization path, and they are not a count of confirmed vulnerable systems. ## Remediation and mitigations
  • Upgrade Starlette to 1.0.1 or later. This is the direct fix. The patch validates the Host header against a hostname pattern and falls back to the socket-level server address when the value is malformed.
  • Patch the full dependency tree, not just the top layer. Upgrading FastAPI alone does not necessarily raise the Starlette version. Inspect the resolved dependency tree and pin Starlette explicitly.
  • Update LiteLLM to 1.84.0 or later if it is deployed, and treat the MCP test endpoints as sensitive.
  • Stop using request.url.path for authorization. The advisory recommends binding checks to endpoints through Starlette requires() or FastAPI Depends() and Security(). Audit the codebase for request.url.path and str(request.url) used in access decisions.
  • Filter malformed Host headers at the edge. A reverse proxy, ingress controller, or WAF configured with a host allowlist that rejects /, ?, #, @, backslash, and space blocks the attack before it reaches the application. This is a mitigation, not a substitute for patching.
  • Validate exposure. X41 D-Sec published an online scanner at badhost.org, along with Semgrep rules and CodeQL queries, to identify affected code paths.
  • Rotate credentials if compromise is suspected. For AI gateways, that includes model provider keys and any tokens stored by the gateway. ## References
  • CISA, "CISA Adds Seven Known Exploited Vulnerabilities to Catalog," 2026-09-02: https://www.cisa.gov/news-events/alerts/2026/09/02/cisa-adds-seven-known-exploited-vulnerabilities-catalog
  • X41 D-Sec, BadHost advisory (X41-2026-002) and badhost.org scanner
  • Starlette GitHub security advisory for CVE-2026-48710, fixed in 1.0.1
  • Horizon3.ai analysis of the CVE-2026-48710 and CVE-2026-42271 chain
  • InfoQ, "BadHost vulnerability puts AI agents, evaluators and LLM gateways at risk"
📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.