Repository navigation
fix(app): restrict default CORS origins to deploy_url in prod mode - #7641
FarhanAliRaza wants to merge 5 commits into
Conversation
The `["*"]` default for `cors_allowed_origins` let any site connect to the backend. In prod mode the default now narrows to the origin of `deploy_url` (or nothing when `deploy_url` is unset), while an explicit `cors_allowed_origins`, from rxconfig or the environment, is used as is. Dev mode keeps allowing any origin. Both the Starlette CORS middleware and the Socket.IO server resolve their origins through one helper. Closes #7640 Claude-Session: https://claude.ai/code/session_01C1xrGYmKsaacgEafTz9BTJ
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ed3738cb94
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
[High impact] The PR appears safe to merge; no new actionable issue was established. SummaryMakes default CORS settings depend on the run mode and changes
Reviews (5) · Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." · Reviewed by Greptile |
There was a problem hiding this comment.
All reported issues were addressed across 6 files
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
Browsers serialize the Origin header with a lowercase host and without the scheme's default port, so `https://Example.com:443/app` must allow `https://example.com`. Also cover CORS enforcement with request-level tests for the HTTP middleware and the Socket.IO origin check. Claude-Session: https://claude.ai/code/session_01C1xrGYmKsaacgEafTz9BTJ
There was a problem hiding this comment.
All reported issues were addressed across 2 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
Merging this PR will improve performance by 5.99%2 warnings
Performance Changes
Tip Curious why performance improved? Comment Comparing Footnotes |
masenf
left a comment
There was a problem hiding this comment.
With reflex run --env prod and the default deploy_url of http://localhost:3000, opening the app via 127.0.0.1:3000 is now rejected. Set deploy_url or cors_allowed_origins for alternate origins.
This is majorly problematic!
Reflex prod mode intentionally runs same origin now, serving the prod frontend build and the websocket from the same asgi stack. And with this change, those same origin connections to the websocket are blocked by socket.io.
I think we need to do the following:
- change default for
deploy_urlin the config to beNone. Add a property forbackend_urlthat gives eitherdeploy_urlorapi_urlwhen the former is unset. Wherever we currently usedeploy_url(like the sitemap plugin), we should move tobackend_urlinstead. - when
deploy_urlis not set in production mode, then DO NOT set CORS options at all -- this defaults to only allowing same origin requests, which is different than allowing cross origin requests from a specific place. socket.io and asgi by default permit same origin requests to come through, which is the sane default that users want.
This keeps common deploy methods working without having to make any config changes, while bolstering security significantly.
Reflex prod mode serves the frontend and the websocket from the same origin, so narrowing CORS to a default deploy_url blocked those same origin connections. deploy_url now defaults to None and is no longer derived from frontend_port; when it is unset in prod mode no CORS middleware is installed and Socket.IO keeps its same-origin default. Config gains a backend_url property (deploy_url, else api_url) and the sitemap plugin builds absolute links from it. Claude-Session: https://claude.ai/code/session_01C1xrGYmKsaacgEafTz9BTJ
|
@masenf thanks, you're right: with the frontend mounted into the backend, a default
Two things worth your eye:
Tests: unit suites for app, config, sitemap, telemetry, export, hosting and site-shared pass; the docs-site suite (727 tests) passes. The full unit run has pre-existing failures in Generated by Claude Code |
There was a problem hiding this comment.
All reported issues were addressed across 12 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
…agupta-e48jze # Conflicts: # tests/units/test_app.py
All Submissions:
Type of change
Changes To Core Features:
Description
closes #7640
The
["*"]default forcors_allowed_originslet any site connect to the backend. This PR makes the default mode-aware, following the design in @masenf's review:deploy_urlunset (the new default): CORS is left unconfigured. NoCORSMiddlewareis installed and the Socket.IO server keeps Engine.IO's same-origin default, which is what a backend that serves its own frontend needs. Cross-origin requests are refused by the browser.deploy_urlset: only that origin is allowed, serialized the way browsers serializeOrigin(lowercase host, no path, default port omitted; non-default ports and IPv6 hosts kept).cors_allowed_origins(fromrxconfig.pyorREFLEX_CORS_ALLOWED_ORIGINS) is used as is in both modes, so["*"]remains an opt-in to the old behavior. Explicitness is detected viaConfig._non_default_attributes.Both enforcement points, the Starlette
CORSMiddlewareand the Socket.IOAsyncServer, resolve their origins through one helper,_cors_allowed_origins()inreflex/app.py.Config changes
deploy_urlnow defaults toNoneinstead ofhttp://localhost:3000, and is no longer derived fromfrontend_port. It is only meant for frontends hosted on a different origin than the backend.Config.backend_urlproperty:deploy_urlwhen set, otherwiseapi_url. The sitemap plugin builds absolute links from it.Notes
AppHarnesspins dev mode before building the app and setsdeploy_urlitself.http://localhost:3000default for its Helm sitemap rewrite; its sitemap now carriesbackend_url. See the review discussion.Tests
Unit tests cover dev vs prod, unset
deploy_url(no middleware, Socket.IO same-origin default), path-bearing and default-portdeploy_urlforms, explicit lists, explicit["*"]via kwargs and via env, request-level enforcement through Starlette'sTestClientand Engine.IO's origin resolution, thebackend_urlfallback, and the sitemap plugin. News fragments added forreflexandreflex-base(both breaking).https://claude.ai/code/session_01C1xrGYmKsaacgEafTz9BTJ