A single question mark in the Host header unlocks every door your middleware thought it had locked
CVE-2026-48710, dubbed BadHost, is a Host header validation bypass in Starlette versions 0.8.3 through 1.0.0 (fixed in 1.0.1). Starlette reconstructs request.url by concatenating the raw HTTP Host header with the request path — f"{scheme}://{host_header}{path}" — without validating the Host value against RFC 9112 / RFC 3986. By injecting a ?, #, or / into the Host header, an attacker makes request.url.path resolve to / (a public route) while the ASGI router still dispatches the request to the *actual* target path (e.g., /admin). Any middleware or endpoint that gates access using request.url.path instead of scope['path'] is instantly bypassed. Because Starlette underpins FastAPI (490M+ monthly PyPI downloads), vLLM, LiteLLM, and most MCP servers, the blast radius is enormous.
The vendor scored this MEDIUM 6.5, which dramatically undersells the real-world risk. The standalone CVSS assessment captures only Confidentiality:Low / Integrity:Low, treating it as a generic information-disclosure-class bug. In practice, the exploit is unauthenticated, requires zero user interaction, works with a single curl command, is KEV-listed as of September 2, 2026, and is already being chained in the wild with CVE-2026-42271 to achieve unauthenticated RCE against LiteLLM gateways — delivering XMRig cryptominers, harvesting secrets from PostgreSQL, and establishing persistence. Microsoft Threat Intelligence published a detailed write-up of the campaign. The vendor MEDIUM label is dangerously wrong for any team running Starlette-based services that are network-reachable.
4 steps from start to impact.
Identify Starlette/FastAPI target
/docs or /openapi.json endpoints). Shodan and FOFA queries for server: uvicorn or fastapi paths return hundreds of thousands of results. Public scanners at badhost.org automate detection.- Target runs Starlette 0.8.3–1.0.0 or FastAPI depending on vulnerable Starlette
- Service is network-reachable (internet or internal network)
- Well-configured reverse proxies (nginx, Envoy, Cloudflare) may normalize or reject malformed Host headers before they reach Starlette
Craft malicious Host header
GET /admin with Host: legitimate.com? (appending a ? character). Starlette concatenates this into https://legitimate.com?/admin and re-parses the result. The ? turns /admin into a query parameter, so request.url.path becomes / — which matches the public root route. The ASGI router, however, dispatches based on the raw scope path, which is still /admin.- Application uses middleware that checks
request.url.pathfor authorization decisions - No upstream proxy strips or rejects the malformed Host header
- Applications using
scope['path']directly for auth checks are not affected - Some load balancers reject Host headers containing
?or#
?, #, or / in Host header values. Access logs showing Host headers with URI-reserved characters.Bypass path-based authorization
request.url.path == '/' and allows the request through. The router dispatches to /admin (or any other protected endpoint). The attacker now has unauthenticated access to every endpoint that was protected by path-based middleware — including admin panels, API key management, model configuration endpoints, and health/debug routes that expose internal state.- Authorization logic relies on
request.urlorrequest.url.path
- Applications using token-based auth (JWT/OAuth) validated at the endpoint level are unaffected by the path bypass alone
- Role-based checks inside the endpoint handler still apply
Chain for RCE (LiteLLM campaign)
- Target is a LiteLLM gateway (or similar Starlette-based app with a secondary injection flaw)
- LiteLLM version < 1.83.7
- Requires a second vulnerability for RCE; BadHost alone yields auth bypass, not code execution
- Network segmentation may limit lateral movement from compromised LLM gateway
The supporting signals.
| In-the-Wild Status | Actively exploited. CISA KEV-listed 2026-09-02. Microsoft Threat Intelligence documented campaigns chaining BadHost + CVE-2026-42271 against LiteLLM gateways for cryptomining and secret theft. |
|---|---|
| Proof-of-Concept | Public and trivial. One-line curl: curl -H 'Host: target?' http://target/admin. Dedicated scanner at badhost.org. GitHub repos: Bhanunamikaze/BadHost-CVE-2026-48710-Exploit, alon710 gist. |
| EPSS | 0.11042 (11.04%) — 96th percentile. Top 4% of all CVEs by predicted exploitation probability. |
| KEV Status | YES — Added 2026-09-02. BOD 22-01 / BOD 26-04 remediation deadline applies to FCEB agencies. |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N — Network-accessible, no auth, no interaction. The Low/Low CIA impact is what keeps the vendor score at 6.5 but understates chained outcomes. |
| Affected Versions | Starlette 0.8.3 – 1.0.0. FastAPI all versions depending on vulnerable Starlette. LiteLLM < 1.83.7. vLLM and MCP servers using bundled Starlette < 1.0.1. |
| Fixed Version | Starlette 1.0.1+. FastAPI users must pin starlette>=1.0.1. LiteLLM 1.83.7+. |
| Scanning/Exposure Data | Shodan queries for server: uvicorn return 200K+ hosts. badhost.org provides a free online scanner. Snyk reports active exploitation attempts observed in telemetry. |
| Disclosure Date | 2026-05-26 (coordinated disclosure). KEV addition 2026-09-02. |
| Reporter | Vulnerability reported by the Starlette maintainers (Kludex). Campaign analysis by Horizon3.ai, Microsoft Threat Intelligence, and Oligo Security. |
noisgate verdict.
The single most decisive factor is the active KEV listing combined with documented in-the-wild exploitation chains converting a MEDIUM-rated auth bypass into unauthenticated RCE against LLM gateways. The trivial exploit complexity (one curl command, no auth, no user interaction) and the massive installed base (FastAPI's 490M+ monthly PyPI downloads) eliminate any friction-based argument for keeping this at MEDIUM.
Why this verdict
- Trivial exploitability: One-line curl command, unauthenticated, no user interaction. Attack complexity is effectively zero for any exposed Starlette service without a normalizing reverse proxy.
- KEV + active campaigns: CISA added this to KEV on 2026-09-02 citing active exploitation. Microsoft documented real-world campaigns chaining BadHost with CVE-2026-42271 for RCE, cryptomining, and credential harvesting against LiteLLM gateways.
- Massive installed base: Starlette is the ASGI layer under FastAPI (490M+ monthly PyPI downloads), vLLM, LiteLLM, and MCP servers. The affected population is not a niche product — it is core AI/ML infrastructure.
- Role multiplier: Starlette/FastAPI is canonically deployed as (c) high-value roles: LLM inference gateways (LiteLLM, vLLM) that hold API keys and model access, MCP agent control planes, and internal API tiers that front production databases. Auth bypass on an LLM gateway yields access to all configured provider API keys, model configurations, and connected data stores. The documented chain ends in full host compromise + secret harvesting + lateral movement — blast radius is host-to-fleet. Because Starlette *is* the framework for these high-value roles (not an incidental dependency), >=10% of Starlette installs occupy high-value positions. Verdict floor: HIGH.
- Friction offset (partial): Reverse proxies (nginx, Envoy, Cloudflare) that normalize Host headers do block the attack. This prevents an upgrade to CRITICAL because a meaningful fraction of production deployments sit behind such proxies. However, dev/staging instances, directly-exposed uvicorn services, and internal network services often lack this protection.
Why not higher?
The standalone vulnerability is an authentication bypass, not direct remote code execution. Achieving RCE requires chaining with a second vulnerability (e.g., CVE-2026-42271 in LiteLLM). Additionally, well-configured reverse proxies that validate Host headers per RFC 9112 neutralize the attack entirely. The CVSS impact is C:L/I:L/A:N for the standalone flaw, and the blast radius requires a secondary bug to reach fleet-scale compromise.
Why not lower?
KEV listing with documented active exploitation campaigns immediately disqualifies MEDIUM or below. The exploit is unauthenticated, requires zero complexity, has public PoC tooling and dedicated scanners, and affects the most popular Python web framework ecosystem. The high-value deployment roles (LLM gateways, AI agent infrastructure) mean the auth bypass alone exposes API keys, model configs, and internal endpoints even without chaining for RCE.
What to do — in priority order.
- Deploy or verify Host header validation on your reverse proxy — Configure nginx (
server_namedirective with strict matching), Envoy (strict host matching in route config), or Cloudflare (managed rules) to reject or normalize Host headers containing?,#, or/characters before traffic reaches Starlette. This is the most effective immediate mitigation — deploy within 3 days per noisgate mitigation SLA since this is KEV-listed with active exploitation, overriding the standard 30-day HIGH timeline. - Audit middleware auth logic for request.url.path usage — Search your codebase for
request.url.pathorrequest.urlin authorization checks. Replace withrequest.scope['path']which uses the raw ASGI path unaffected by Host header manipulation. Semgrep rule:pattern: request.url.path. Deploy code changes within the mitigation window. - Pin starlette>=1.0.1 in all requirements files — Run
pip install --upgrade starlette>=1.0.1across all environments. For FastAPI projects, verify the resolved Starlette version withpip show starlette. For LiteLLM, upgrade to >=1.83.7. Prioritize internet-facing and LLM gateway deployments first. - Monitor for Host header anomalies in access logs — Create SIEM alerts for HTTP requests where the Host header contains
?,#, or path separators. Correlate with successful (2xx) responses to admin or protected endpoints. This provides detection coverage while patching is in progress.
- WAF path-based rules alone — The attack manipulates the Host header, not the URL path. Standard WAF rules that inspect the request URI will not catch the malformed Host header unless specifically configured for Host header validation.
- Token-based auth at the middleware layer using request.url — If your JWT/OAuth validation middleware uses
request.url.pathto decide *whether* to enforce auth (e.g., skipping auth for/health), the bypass still works even though the token validation logic itself is sound. - Network segmentation without Host header normalization — Putting the service on an internal network reduces exposure but does not eliminate it; any internal attacker or compromised adjacent host can still exploit the flaw.
Crowdsourced verification payload.
Run this script on any host with pip access to check installed Starlette versions. Execute as the same user that runs your Python applications: bash check_badhost.sh. No elevated privileges required.
#!/usr/bin/env bash
# check_badhost.sh — Detect CVE-2026-48710 (BadHost) in installed Starlette
# Usage: bash check_badhost.sh
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
VULN_CVE="CVE-2026-48710"
FIXED_VERSION="1.0.1"
echo "[*] Checking for $VULN_CVE (Starlette BadHost)"
# Check if pip is available
if ! command -v pip &>/dev/null && ! command -v pip3 &>/dev/null; then
echo "UNKNOWN — pip not found. Check Python environments manually."
exit 2
fi
PIP_CMD=$(command -v pip3 2>/dev/null || command -v pip 2>/dev/null)
# Get installed starlette version
INSTALLED=$($PIP_CMD show starlette 2>/dev/null | grep -i '^Version:' | awk '{print $2}')
if [ -z "$INSTALLED" ]; then
echo "UNKNOWN — starlette is not installed in this Python environment."
echo "[*] Check other virtualenvs: find / -name 'starlette' -path '*/site-packages/*' 2>/dev/null"
exit 2
fi
echo "[*] Installed starlette version: $INSTALLED"
echo "[*] Fixed version: >= $FIXED_VERSION"
# Compare versions using sort -V
LOWEST=$(printf '%s\n%s\n' "$INSTALLED" "$FIXED_VERSION" | sort -V | head -n1)
if [ "$LOWEST" = "$FIXED_VERSION" ] || [ "$INSTALLED" = "$FIXED_VERSION" ]; then
echo "PATCHED — starlette $INSTALLED >= $FIXED_VERSION"
exit 0
else
echo "VULNERABLE — starlette $INSTALLED < $FIXED_VERSION"
echo "[!] Upgrade immediately: pip install 'starlette>=$FIXED_VERSION'"
exit 1
fiIf you remember one thing.
starlette to >=1.0.1 and litellm to >=1.83.7 on all internet-facing and LLM gateway hosts first, (3) verify your reverse proxy (nginx, Envoy, Cloudflare) rejects or normalizes Host headers containing ?, #, or / — this is your fastest compensating control if patching takes time, (4) audit all custom middleware for request.url.path usage and switch to scope['path']. The noisgate remediation SLA for HIGH is 180 days for the full fleet, but KEV-listed active exploitation means you should treat internet-facing instances as a same-day emergency and complete internal hosts within 30 days.Sources
- Snyk Vulnerability Database — SNYK-PYTHON-STARLETTE-16881242
- Horizon3.ai — CVE-2026-42271 Chained with CVE-2026-48710
- CISA KEV Addition — September 2, 2026
- Microsoft Threat Intelligence — Securing AI Gateways
- Oligo Security — LiteLLM RCE Detection and Blocking
- The Hacker News — LiteLLM Flaw Exploited in the Wild
- BadHost PoC and Exploit Repository
- Belgium CCB Advisory — Starlette Framework Vulnerability
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.