Skip to content

Add allow_private_network in CORSMiddleware#3065

Merged
Kludex merged 5 commits intomainfrom
add-pna-checks-cors
Nov 4, 2025
Merged

Add allow_private_network in CORSMiddleware#3065
Kludex merged 5 commits intomainfrom
add-pna-checks-cors

Conversation

@Kludex Kludex requested a review from Copilot November 1, 2025 22:21
Comment thread starlette/middleware/cors.py Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for Private Network Access (PNA) to the CORS middleware by implementing the allow_private_network configuration parameter. This enables servers to control whether cross-origin requests from public networks to private networks are permitted.

Key changes:

  • Added allow_private_network parameter to CORSMiddleware constructor
  • Implemented PNA header handling in preflight responses
  • Fixed a typo in test comment ("diallowed" → "disallowed")

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
starlette/middleware/cors.py Added allow_private_network parameter, type annotations for dict variables, and logic to handle Access-Control-Request-Private-Network header in preflight requests
tests/middleware/test_cors.py Fixed typo in comment, added comprehensive tests for PNA allowed and disallowed scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread starlette/middleware/cors.py
Comment thread tests/middleware/test_cors.py
Copy link
Copy Markdown
Contributor

@Zaczero Zaczero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to Vary: Access-Control-Request-Private-Network, just like we currently do for Origin. Conditionally added whenever allow_private_network is set.

@Kludex
Copy link
Copy Markdown
Owner Author

Kludex commented Nov 2, 2025

I think we want to Vary: Access-Control-Request-Private-Network, just like we currently do for Origin. Conditionally added whenever allow_private_network is set.

But then, are you saying we should also add for the access-control-request-header and access-control-request-method as well?

The Django and Flask CORS do not add it to the Vary - this doesn't mean they are right, just a data point. But can you find a reference or justify it?

@Zaczero
Copy link
Copy Markdown
Contributor

Zaczero commented Nov 2, 2025

My logic is that Vary makes it explicit to the caches that the same request will have a different response based on the headers sent. And this is the case here. When the request header is sent, it will have different response headers, so the response varies on that.

Including a Vary header ensures that responses are separately cached based on the headers listed in the Vary field.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Vary

Also found this:
https://stackoverflow.com/questions/65675056/why-add-vary-on-access-control-request-method-acrh-and-origin-when-options-meth

To my limited knowledge on this topic, Vary seems like it will make the implementation more correct (doesn't mean it's necessary). We already Vary on Origin so the intention is that we want to support caching OPTIONS responses. May as well expand Vary to cover all varying headers.

@Kludex
Copy link
Copy Markdown
Owner Author

Kludex commented Nov 2, 2025

But then, should the other access headers be also included?

I'm having an inclination to not do it, unless someone did it in any other CORS implementation (in any framework from any language).

@Zaczero
Copy link
Copy Markdown
Contributor

Zaczero commented Nov 2, 2025

From the stackoverflow it explicitly mentions https://github.com/rs/cors as having this behavior. I haven't searched more.

If this decision was up to me, I would ensure Vary contains all varying headers correctly. The cost is little, and when someone decides to cache OPTIONS responses the setup will be simpler and less bug-prone. It would make the app more explicit about cache handling which is a good thing.

AI research on this: https://claude.ai/public/artifacts/860f4896-69c0-4416-8066-ff9bd73c1a37

The official specifications provide minimal guidance on Vary headers for CORS, creating a gap between spec and practice. Vary: Origin is recommended but not strictly required by specifications, yet is absolutely critical in production environments with CDNs or caching layers. Vary: Access-Control-Request-Headers appears in no specification but prevents real cache poisoning issues.

Comment thread docs/middleware.md Outdated
@Kludex
Copy link
Copy Markdown
Owner Author

Kludex commented Nov 4, 2025

@Zaczero I'll merge this as is, because the "Vary" is actually an issue with the other request headers as well. Would you like to contribute with that?

This https://github.com/rs/cors has a beautiful code. Super easy to understand. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CORSMiddleware with Access-Control-Allow-Private-Network header

3 participants