On May 22, 2026, a critical vulnerability in the Starlette ASGI framework was publicly disclosed. CVE-2026-48710, nicknamed “BadHost,” allows an unauthenticated attacker to bypass every path-based authentication check on any Starlette server — including FastAPI applications, vLLM inference servers, LiteLLM proxies, and MCP gateway implementations — using a single character injected into the HTTP Host header.

The patch (Starlette 1.0.1) shipped one day before public disclosure, giving operators effectively zero lead time before exploit details became public.

If you’re running any Python-based AI agent infrastructure, this is not optional maintenance.


What BadHost Does

Starlette constructs request.url by concatenating the HTTP Host header with the request path, then re-parses the result. The Host value is not validated against RFC 9112 or RFC 3986 grammar before reconstruction.

An attacker who injects characters like /, ?, or # into the Host header causes the reconstructed URL’s path component to diverge from the actual path the ASGI server routed against. The scope["path"] value — what the server actually received and routed — says /admin/users. The request.url.path value — what any middleware relying on it sees — says /public/assets.

Any authentication middleware, route guard, or permission decorator that reads request.url.path to decide whether to require credentials will see the wrong path. The actual request is protected. The reconstructed view of it is not.

Result: an unauthenticated request reaches your /admin, /v1/completions, /metrics, or any other protected endpoint.


Who Is Affected

The blast radius is wide. Starlette receives approximately 325 million downloads per week and underlies the majority of Python AI infrastructure:

Framework / Tool Starlette Dependency Typical Auth Pattern
FastAPI Direct dependency Path-based middleware common
vLLM FastAPI-based API server Bearer token via path middleware
LiteLLM proxy FastAPI-based API key auth via middleware
MCP servers (many) FastAPI or raw Starlette Path-based guards on tool endpoints
Text Generation Inference FastAPI-based Header + path checks
OpenAI-compatible proxies Typically FastAPI Route-level auth

If you:

  • Run any FastAPI-based model-serving endpoint
  • Host an MCP server with protected tool routes
  • Use LiteLLM as a gateway in front of multiple model providers
  • Self-host vLLM with API key authentication
  • Run any custom ASGI application with path-based auth middleware

…you need to check your Starlette version and your auth middleware implementation.


How the Attack Works

The exploit is a one-line HTTP modification. A request to your protected /v1/completions endpoint normally looks like:

POST /v1/completions HTTP/1.1
Host: your-server.example.com
Authorization: Bearer <key>

A BadHost payload looks like:

POST /v1/completions HTTP/1.1
Host: your-server.example.com/public
Authorization: (absent)

Starlette reconstructs request.url as http://your-server.example.com/public/v1/completions, then re-parses it. request.url.path becomes /public/v1/completions. Middleware that checks if request.url.path.startswith("/public") sees a match and skips auth. The actual ASGI scope still routed the request to your /v1/completions handler.

The attacker gets an authenticated response with no credentials supplied.


Fix: Upgrade to Starlette 1.0.1

The primary fix is a package upgrade:

pip install "starlette>=1.0.1"

For FastAPI:

pip install "fastapi>=0.115.x"  # verify FastAPI's starlette floor
pip install "starlette>=1.0.1"

Container and virtualenv rebuilds required. LLM tooling commonly pins or vendors Starlette. Upgrading your requirements file is not enough if the package is embedded in a frozen container layer or a bundled distribution. Rebuild and redeploy every container image, virtualenv, and bundled artifact.

Verify your installed version:

python -c "import starlette; print(starlette.__version__)"

You want 1.0.1 or later.


Fix: Harden Your Middleware

Even after upgrading, audit your authentication middleware for the root-cause pattern. The vulnerable pattern:

# VULNERABLE — uses request.url.path
async def auth_middleware(request: Request, call_next):
    if request.url.path.startswith("/admin"):
        token = request.headers.get("Authorization")
        if not token or not verify(token):
            raise HTTPException(status_code=401)
    return await call_next(request)

The safe pattern:

# SAFE — uses scope["path"] directly
async def auth_middleware(request: Request, call_next):
    path = request.scope["path"]  # not request.url.path
    if path.startswith("/admin"):
        token = request.headers.get("Authorization")
        if not token or not verify(token):
            raise HTTPException(status_code=401)
    return await call_next(request)

The scope["path"] value is set by the ASGI server from the actual routed request and cannot be manipulated via the Host header. Replace request.url.path with request.scope["path"] everywhere authentication decisions are made.

Apply this audit to:

  • All custom middleware (BaseHTTPMiddleware, @app.middleware("http"))
  • All FastAPI dependencies that check routes
  • All decorator-based route guards
  • All third-party auth libraries that proxy to Starlette request parsing (check their changelogs)

Detection Tools

X41 D-Sec (the research firm that discovered BadHost during an OSTIF-sponsored vLLM security audit) has released free tooling:

  • Remote scanner: badhost.org — point it at any HTTP endpoint to check for the vulnerability without reading source code
  • Semgrep rules: detect the request.url.path pattern in your codebase
  • CodeQL queries: static analysis for CI/CD integration
  • PoC repository: github.com/x41sec/poc

Running the remote scanner against your staging or dev endpoints before deploying is a reasonable first check. The Semgrep rules are the most actionable for a codebase audit — they find every instance of the vulnerable pattern across your application.


Why This Matters Specifically for AI Agent Infrastructure

Most AI agent deployments have a security architecture that assumes authentication happens at the perimeter. An authenticated session reaches the model-serving layer; unauthenticated traffic is blocked before it gets there. BadHost breaks that assumption at the framework level.

The practical consequences for common builder architectures:

MCP servers: Many MCP implementations use path-based routing to separate tool endpoints (/tools/) from health checks (/health). A BadHost attack can reach tool handlers — which may have file system access, database connections, or external API credentials — without authentication.

LiteLLM proxies: LiteLLM commonly protects its /v1/* API endpoints behind API key middleware. A BadHost payload reaches those endpoints unauthenticated, exposing your upstream API keys and the model access they control.

vLLM API servers: vLLM’s API key check runs through FastAPI middleware. Bypassing it grants full access to your GPU inference endpoint — generating text at your compute cost with no rate limiting.

Evaluation dashboards and agent harnesses: Internal tooling often has lighter perimeter security on the assumption that path-based middleware will handle access control. BadHost eliminates that layer.


Timeline

Date Event
January 2026 X41 D-Sec discovers BadHost during OSTIF-sponsored vLLM audit
May 21, 2026 Starlette 1.0.1 patch ships (coordinated disclosure)
May 22, 2026 Public disclosure — exploit details become public
May 22+, 2026 badhost.org scanner, Semgrep rules, CodeQL queries released

The one-day window between patch and disclosure is tight by industry standards. If you have not applied the patch since May 21, assume your exposure window has been open with public exploit knowledge available.


Action Checklist

For any Python AI backend (FastAPI, vLLM, LiteLLM, MCP server, custom ASGI):

  • Check starlette --version (or pip show starlette) — target 1.0.1+
  • Upgrade Starlette in all requirements files, lock files, and pinned dependencies
  • Rebuild and redeploy every container image and bundled virtualenv
  • Run the badhost.org scanner against staging endpoints
  • Audit all auth middleware: replace request.url.path with request.scope["path"]
  • Add Semgrep rule to CI to catch regressions
  • Review third-party auth libraries for Starlette version dependencies

The vulnerability is severe, the patch is available, and the detection tooling is free. There is no good reason to leave this unpatched.


CVE-2026-48710 was discovered by X41 D-Sec during an OSTIF-sponsored security audit of vLLM. Disclosure was coordinated with the Starlette maintainers. Research was conducted using publicly available security advisories, technical write-ups, and the OSTIF disclosure post. ChatForest did not independently reproduce the exploit.