The Fix
Improves the ProxyHeadersMiddleware to correctly handle client addresses from trusted proxies, addressing the issue where clients were reported as [None, 0].
Based on closed Kludex/uvicorn issue #1068 · PR/commit linked
@@ -93,10 +93,12 @@ Options:
--date-header / --no-date-header
Enable/Disable default Date header.
- --forwarded-allow-ips TEXT Comma separated list of IPs to trust with
- proxy headers. Defaults to the
- $FORWARDED_ALLOW_IPS environment variable if
# app.py
from tests.response import Response
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
async def inner(scope, receive, send):
scheme = scope["scheme"]
host, port = scope["client"]
addr = "%s://%s:%d" % (scheme, host, port)
response = Response("Remote: " + addr, media_type="text/plain")
await response(scope, receive, send)
app = ProxyHeadersMiddleware(inner, trusted_hosts=['127.0.0.1'])
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Option A — Apply the official fix\nImproves the ProxyHeadersMiddleware to correctly handle client addresses from trusted proxies, addressing the issue where clients were reported as [None, 0].\nWhen NOT to use: Do not use this fix if the application is not behind a trusted proxy.\n\n
Why This Fix Works in Production
- Trigger: E AssertionError: assert 'Remote: https://None:0' == 'Remote: https://1.2.3.4:0'
- Mechanism: ProxyHeadersMiddleware fails to correctly handle client addresses from trusted proxies
- If left unfixed, this can cause silent data inconsistencies that propagate (bad cache entries, incorrect downstream decisions).
Why This Breaks in Prod
- Shows up under Python 3.9.1 in real deployments (not just unit tests).
- ProxyHeadersMiddleware fails to correctly handle client addresses from trusted proxies
- Surfaces as: assert response.text == response_text
Proof / Evidence
- GitHub issue: #1068
- Fix PR: https://github.com/kludex/uvicorn/pull/2468
- Reproduced locally: No (not executed)
- Last verified: 2026-02-11
- Confidence: 0.70
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.55
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“Hi @jchristgit , yeah send us a repro, in that case the trusted host param you are passing and the headers received should be good…”
“> I will add a few tests and will try to fix implementation, but the Iack of ready implementations on Github confuses me. Maybe someone…”
“could do that, this works but not certain of the edge case or implications”
“In my case i use cloudflare.com and it proxy the requests by its Global CDNs when i get a request on uvicorn it shows to…”
Failure Signature (Search String)
- E AssertionError: assert 'Remote: https://None:0' == 'Remote: https://1.2.3.4:0'
Error Message
Stack trace
Error Message
-------------
assert response.text == response_text
E AssertionError: assert 'Remote: https://None:0' == 'Remote: https://1.2.3.4:0'
E - Remote: https://1.2.3.4:0
E ? ^^^^^^^
E + Remote: https://None:0
E ? ^^^^
Minimal Reproduction
# app.py
from tests.response import Response
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
async def inner(scope, receive, send):
scheme = scope["scheme"]
host, port = scope["client"]
addr = "%s://%s:%d" % (scheme, host, port)
response = Response("Remote: " + addr, media_type="text/plain")
await response(scope, receive, send)
app = ProxyHeadersMiddleware(inner, trusted_hosts=['127.0.0.1'])
Environment
- Python: 3.9.1
What Broke
Clients are reported as [None, 0] instead of their actual addresses, causing incorrect client identification.
Why It Broke
ProxyHeadersMiddleware fails to correctly handle client addresses from trusted proxies
Fix Options (Details)
Option A — Apply the official fix
Improves the ProxyHeadersMiddleware to correctly handle client addresses from trusted proxies, addressing the issue where clients were reported as [None, 0].
Fix reference: https://github.com/kludex/uvicorn/pull/2468
Last verified: 2026-02-11. Validate in your environment.
When NOT to Use This Fix
- Do not use this fix if the application is not behind a trusted proxy.
Verify Fix
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Did This Fix Work in Your Case?
Quick signal helps us prioritize which fixes to verify and improve.
Prevention
- Capture the exact failing error string in logs and tests so you can reproduce via a minimal script.
- Pin production dependencies and upgrade only with a reproducible test that hits the failing path.
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.