CVE-2026-48710: Starlette & FastAPI BadHost Path Smuggling & Auth Bypass
HERMES THREAT SCORE & OPERATIONAL EXPLOITABILITY
Target:Starlette ASGI Framework & FastAPI Microservices (β€ 1.0.0) Elevated to 92 HIGH by Hermes due to widespread adoption across modern AI inference gateways (vLLM, LiteLLM, Ollama proxies), confirmed active exploitation in the wild, and listing on the CISA KEV catalog (September 2, 2026).
CVE-2026-48710: Starlette & FastAPI BadHost Path Smuggling & Auth BypassVULNERABILITY
Software platform affected by security vulnerabilities and agentic attack patterns.
π Why is this related? (Evidence & Provenance)
“Confirmed security vulnerability in Starlette / FastAPI ASGI Framework documented in Hermes dossier.”
- [vulnerability_report]
- [government_confirmation]CISA verified active exploitation in the wild and mandated federal remediation deadline in KEV entry. — Source: Cybersecurity & Infrastructure Security Agency (CISA): CISA Adds CVE-2026-59822 to Known Exploited Vulnerabilities Catalog (Reliability: VERY_HIGH)
Root Cause Analysis
Section titled βRoot Cause AnalysisβIn modern asynchronous Python web architectures, the ASGI (Asynchronous Server Gateway Interface) specification governs communication between the HTTP server (e.g., Uvicorn, Hypercorn, Granian) and the application framework (Starlette, FastAPI):
ASGI Scope vs. Starlette request.url Desynchronization ("BadHost"):
Attacker Submits Crafted HTTP Request: GET /admin/models/delete HTTP/1.1 Host: api.target.corp/public# β βΌ [ASGI Server: Uvicorn / Hypercorn] Parses raw HTTP packet into standard ASGI connection scope: scope = { "type": "http", "path": "/admin/models/delete", <ββ Canonical Raw Endpoint "headers": [(b"host", b"api.target.corp/public#")] } β βΌ [Starlette Application Layer: request.py] Reconstructs high-level `request.url` object via unvalidated string joining: url = f"{scheme}://{host}{root_path}{path}" url = "https://" + "api.target.corp/public#" + "" + "/admin/models/delete" β βΌ [Standard Library urllib.parse.urlsplit(url)] Interprets `#` as fragment boundary or `/` as path boundary: β’ scheme: "https" β’ netloc: "api.target.corp" β’ path: "/public" <ββ SPOOFED EVALUATED PATH β’ fragment: "/admin/models/delete" β βΌ Security Middleware Evaluation Check: ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Auth Middleware: `if request.url.path.startswith("/admin"): require_auth()`β β Evaluates: `request.url.path` == "/public" -> PASS (NO AUTH REQUIRED) β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β βΌ Underlying Router Execution: Router dispatches request using raw `scope["path"]` -> Executes `/admin/models/delete`The Unvalidated Host Concatenation Flaw
Section titled βThe Unvalidated Host Concatenation FlawβIn Starlette versions prior to 1.0.1, the Request.url property in starlette/datastructures.py reconstructed the full URL by reading the Host header directly:
# Vulnerable code in Starlette <= 1.0.0@propertydef url(self) -> URL: if not hasattr(self, "_url"): # Extracts raw Host header from client request host_header = self.headers.get("host") if host_header: url = f"{self.scope['scheme']}://{host_header}{self.scope['path']}" else: # Fallback to server IP server = self.scope.get("server") url = f"{self.scope['scheme']}://{server[0]}:{server[1]}{self.scope['path']}" self._url = URL(url) return self._urlNotice that the host_header was passed directly into string interpolation without validating that it adhered to RFC 9112 (HTTP/1.1 Host Grammar) or RFC 3986 (URI Authority Components): host = uri-host [ ":" port ].
When an attacker supplies a Host header containing /, ?, or # characters (such as Host: example.com/public? or Host: example.com/docs#), Pythonβs urllib.parse.urlsplit() reinterprets the authority boundary. The injected characters trick the parser into shifting the actual requested path (/admin/private) into the query string or URL fragment, while the path extracted by request.url.path reflects the attackerβs spoofed prefix (/public).
Because middleware modules (FastAPI dependencies, authentication decorators, CORS handlers) typically inspect request.url.path, while the internal ASGI router dispatches handlers based on the raw scope["path"], the two components become completely desynchronized.
Exploit Mechanics & Attack Scenarios
Section titled βExploit Mechanics & Attack ScenariosβAn attacker needs direct network access to the FastAPI/Starlette application, requiring no authentication, tokens, or prior access credentials.
1. Bypassing Path-Based Authentication
Section titled β1. Bypassing Path-Based AuthenticationβConsider a typical FastAPI microservice protecting an administrative AI management route:
@app.middleware("http")async def verify_admin_token(request: Request, call_next): # Security check inspecting high-level request.url.path if request.url.path.startswith("/admin"): token = request.headers.get("X-Admin-Key") if token != "SECRET_PRODUCTION_KEY": return Response(status_code=403, content="Forbidden") return await call_next(request)
@app.post("/admin/models/unload")def unload_model(name: str): return {"status": "model unloaded", "target": name}The attacker transmits a raw HTTP/1.1 request manipulating the Host header:
POST /admin/models/unload?name=llama3-70b HTTP/1.1Host: ai-gateway.corp/health#User-Agent: Mozilla/5.0Content-Type: application/json
{}Execution Trace:
- Starlette reconstructs the URL:
https://ai-gateway.corp/health#/admin/models/unload?name=llama3-70b. request.url.pathevaluates strictly to"/health".- The authentication middleware evaluates
"/health".startswith("/admin")->False. Security check is bypassed. - The Starlette routing engine receives the request, matches the underlying ASGI
scope["path"](/admin/models/unload), and dispatches the administrative handler. - The model is unloaded from GPU memory without any administrative credentials.
2. Impact on AI Agent Gateways & Model Inference Servers
Section titled β2. Impact on AI Agent Gateways & Model Inference ServersβIn agentic architectures (LiteLLM, vLLM, Ollama proxies), Starlette and FastAPI are used as the primary API front-ends:
- Tool & Prompt Extraction: Adversaries bypass
/admin/promptsor/api/v1/toolsauthentication barriers, leaking enterprise system instructions and confidential RAG knowledge bases. - Denial of Service (GPU Exhaustion): Invoking internal batch generation or model-swapping endpoints without API keys or rate-limiting guards.
- Tenant Isolation Breakdown: Multi-tenant SaaS gateways mapping customer organizations via URL paths (
/tenants/{tenant_id}/...) can be manipulated to access adjacent tenant memory and vector embeddings.
Forensic Markers & Detection Engineering
Section titled βForensic Markers & Detection EngineeringβDFIR analysts and SOC engineers triaging suspected CVE-2026-48710 exploitation should look for the following telemetry artifacts:
1. Ingress & Reverse Proxy Telemetry
Section titled β1. Ingress & Reverse Proxy TelemetryβExamine WAF, Nginx, Envoy, or Cloudflare logs for non-compliant Host headers:
- Delimiter Characters in Host Field: HTTP requests where the
$http_hostorHostheader contains/,?,#, or@:GET /admin/keys HTTP/1.1 | Host: 10.0.4.12/public# | Status: 200 - Status Code Discrepancies: Requests targeting administrative endpoints returning
200 OKor204 No Contentfrom IP addresses that have never completed an OAuth2 or API key exchange.
2. Application-Level Execution Logs
Section titled β2. Application-Level Execution Logsβ- Starlette/Uvicorn access logs recording requests where the logged path does not match external load-balancer routing paths:
INFO: 198.51.100.22:45210 - "POST /admin/models/unload HTTP/1.1" 200 OK
- Absence of authentication token parameters or user identifiers in downstream application transaction logs for requests executing privileged endpoints.
Detection Rules
Section titled βDetection Rulesβtitle: Malformed HTTP Host Header Containing URL Delimiters (CVE-2026-48710 BadHost)id: 48710b01-4f10-4e2b-a487-100000048710status: experimentaldescription: Detects HTTP requests bearing illegal characters (/ ? # @) within the Host request header, indicating an attempt to exploit CVE-2026-48710 path smuggling in Starlette/FastAPI.references: - https://github.com/encode/starlette/security/advisories/GHSA-7488-6r32-c95q - https://www.cisa.gov/known-exploited-vulnerabilities-catalogauthor: Hermes Codex CTIdate: 2026-09-08logsource: category: webserver product: web_proxydetection: selection_host: cs-header_host|re: '.*[\/\?\#\@].*' condition: selection_hostfalsepositives: - Non-RFC-compliant legacy embedded testing tools (very rare on public interfaces).level: hightags: - attack.initial_access - attack.t1190 - cve.2026.48710alert http $EXTERNAL_NET any -> $HTTP_SERVERS any ( \ msg:"ET WEB_SPECIFIC_APPS Starlette / FastAPI BadHost Host Header Path Smuggling (CVE-2026-48710)"; \ flow:established,to_server; \ http.header; content:"Host|3a|"; pcre:"/Host\x3a\s*[^\r\n\/]+[\x2f\x5c]/Hmi"; \ reference:cve,2026-48710; \ reference:url,hermes-codex.vercel.app/cve/2026/cve-2026-48710/; \ classtype:web-application-attack; \ sid:202648710; rev:1; \)Mitigation & Hardening Architecture
Section titled βMitigation & Hardening Architectureβ1. Direct Dependency Upgrade
Section titled β1. Direct Dependency UpgradeβUpgrade starlette in your project dependencies immediately:
# Using pippip install --upgrade "starlette>=1.0.1"
# Using uvuv add "starlette>=1.0.1"
# Using Poetrypoetry add "starlette>=1.0.1"If using fastapi, ensure it pulls in starlette >= 1.0.1:
pip install --upgrade "fastapi[standard]>=0.115.0"2. Edge Reverse Proxy Normalization
Section titled β2. Edge Reverse Proxy NormalizationβEven with patched applications, edge ingress controllers should strictly sanitize incoming Host headers to adhere to RFC 3986.
# Reject any request with slashes or backslashes in Hostif ($http_host ~* "[\/\\]") { return 400 "Invalid Host Header";}proxy_set_header Host $host;# Caddyfile virtual patch@badhost header_regexp Host [\/\?\#\@]respond @badhost "Bad Request" 400Sources & Technical References
Section titled βSources & Technical Referencesβ- CISA Known Exploited Vulnerabilities: BOD 26-04 Entry for CVE-2026-48710
- GitHub Security Advisory: GHSA-7488-6r32-c95q β Starlette BadHost Vulnerability
- NIST National Vulnerability Database: CVE-2026-48710 Detail
- Related Codex Studies: Model Context Protocol Security and AI Agent Misconfigurations