The Fix
Upgrade to version 0.13.4 or later.
Based on closed Kludex/starlette issue #510 · PR/commit linked
@@ -98,7 +98,6 @@ def preflight_response(self, request_headers: Headers) -> Response:
requested_method = request_headers["access-control-request-method"]
requested_headers = request_headers.get("access-control-request-headers")
- requested_cookie = "cookie" in request_headers
headers = dict(self.preflight_headers)
import uvicorn
from starlette.applications import Starlette
from starlette.responses import PlainTextResponse
from starlette.middleware.cors import CORSMiddleware
app = Starlette()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_headers=["*"],
allow_methods=["*"],
)
@app.route("/")
def homepage(request):
return PlainTextResponse("Homepage", status_code=200)
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=5100)
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Option A — Upgrade to fixed release\nUpgrade to version 0.13.4 or later.\nWhen NOT to use: Do not apply this fix if the application requires retaining the origin for specific requests.\n\n
Why This Fix Works in Production
- Trigger: 'access-control-allow-origin' header seems to "leak" between requests
- Mechanism: The 'Access-Control-Allow-Origin' header incorrectly retains the origin from previous credentialed requests
- Why the fix works: Fixes a CORS issue where the 'Access-Control-Allow-Origin' header leaks between credentialed and non-credentialed requests. (first fixed release: 0.13.4).
- If left unfixed, this can cause silent data inconsistencies that propagate (bad cache entries, incorrect downstream decisions).
Why This Breaks in Prod
- The 'Access-Control-Allow-Origin' header incorrectly retains the origin from previous credentialed requests
- Production symptom (often without a traceback): 'access-control-allow-origin' header seems to "leak" between requests
Proof / Evidence
- GitHub issue: #510
- Fix PR: https://github.com/encode/starlette/pull/513
- First fixed release: 0.13.4
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.75
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.57
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“Re "cookies": the var here is not used: https://github.com/blueyed/starlette/blob/1fc5cee3d603fa917facf66cf8259c5e05635c10/starlette/middleware/cors.py#L101”
“@steinnes Can you check https://github.com/encode/starlette/pull/513, please?”
Failure Signature (Search String)
- 'access-control-allow-origin' header seems to "leak" between requests
Copy-friendly signature
Failure Signature
-----------------
'access-control-allow-origin' header seems to "leak" between requests
Error Message
Signature-only (no traceback captured)
Error Message
-------------
'access-control-allow-origin' header seems to "leak" between requests
Minimal Reproduction
import uvicorn
from starlette.applications import Starlette
from starlette.responses import PlainTextResponse
from starlette.middleware.cors import CORSMiddleware
app = Starlette()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_headers=["*"],
allow_methods=["*"],
)
@app.route("/")
def homepage(request):
return PlainTextResponse("Homepage", status_code=200)
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=5100)
What Broke
Non-credentialed requests receive incorrect CORS headers, leading to potential security issues.
Why It Broke
The 'Access-Control-Allow-Origin' header incorrectly retains the origin from previous credentialed requests
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
Upgrade to version 0.13.4 or later.
Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.
Fix reference: https://github.com/encode/starlette/pull/513
First fixed release: 0.13.4
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- Do not apply this fix if the application requires retaining the origin for specific requests.
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.
Version Compatibility Table
| Version | Status |
|---|---|
| 0.13.4 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.