From 8b97d279531aca473c63093b1bfac01d95073ad3 Mon Sep 17 00:00:00 2001 From: Devanshu Rajesh Chicholikar Date: Sun, 1 Mar 2026 11:22:40 -0500 Subject: [PATCH 1/2] infra: add ALLOW_ORIGIN_REGEX for Vercel preview deploy CORS (OPE-56) Vercel preview deploys get dynamic URLs like: opencodeintel-git-feat-xxx.vercel.app These need to call the Railway backend but get CORS blocked because ALLOWED_ORIGINS only has the production domain. FastAPI CORSMiddleware supports allow_origin_regex -- now configurable via ALLOW_ORIGIN_REGEX env var. Set on Railway to: https://.*\.vercel\.app This allows all Vercel preview URLs to call the backend while keeping the explicit ALLOWED_ORIGINS list for production. Also added GITHUB_TOKEN to optional startup vars (used by /repos/analyze). --- .env.example | 3 +++ backend/config/startup_checks.py | 2 ++ backend/main.py | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/.env.example b/.env.example index 12193bc..7d06900 100644 --- a/.env.example +++ b/.env.example @@ -40,6 +40,9 @@ GITHUB_REDIRECT_URI=http://localhost:3000/auth/github/callback # CORS Configuration (Security) # Comma-separated list of allowed origins ALLOWED_ORIGINS=http://localhost:3000 +# Regex for dynamic CORS origins (Vercel preview deploys) +# Set on Railway to allow PR preview URLs to call the backend +# ALLOW_ORIGIN_REGEX=https://.*\.vercel\.app # Redis (auto-configured in Docker, set REDIS_URL in Railway) REDIS_HOST=redis diff --git a/backend/config/startup_checks.py b/backend/config/startup_checks.py index 5aa0e60..4d8510e 100644 --- a/backend/config/startup_checks.py +++ b/backend/config/startup_checks.py @@ -29,6 +29,8 @@ ("GITHUB_CLIENT_ID", "GitHub OAuth client ID", "GitHub repo import disabled"), ("GITHUB_CLIENT_SECRET", "GitHub OAuth client secret", "GitHub repo import disabled"), ("DISCORD_FEEDBACK_WEBHOOK", "Discord webhook for feedback", "Feedback notifications disabled"), + ("ALLOW_ORIGIN_REGEX", "CORS regex for preview deploys", "Only explicit origins allowed"), + ("GITHUB_TOKEN", "GitHub API token for repo analysis", "Using unauthenticated rate limit (60/hr)"), ] diff --git a/backend/main.py b/backend/main.py index 8e7d12e..a466f70 100644 --- a/backend/main.py +++ b/backend/main.py @@ -75,9 +75,13 @@ async def dispatch(self, request: Request, call_next): app.add_middleware(RequestSizeLimitMiddleware) ALLOWED_ORIGINS = os.getenv("ALLOWED_ORIGINS", "http://localhost:3000").split(",") +# Allow Vercel preview deploys (dynamic subdomains) so PRs can be tested +# against the production backend without CORS issues +ALLOW_ORIGIN_REGEX = os.getenv("ALLOW_ORIGIN_REGEX", "") app.add_middleware( CORSMiddleware, allow_origins=ALLOWED_ORIGINS, + allow_origin_regex=ALLOW_ORIGIN_REGEX or None, allow_credentials=True, allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], allow_headers=["Authorization", "Content-Type"], From afa7755ea6ef109ea21f2f6956185467493d5e30 Mon Sep 17 00:00:00 2001 From: Devanshu Rajesh Chicholikar Date: Sun, 1 Mar 2026 11:28:49 -0500 Subject: [PATCH 2/2] fix: scope CORS regex to project name, not all Vercel apps https://.*\.vercel\.app is too broad -- allows any Vercel project to call our backend. Scoped to https://opencodeintel.*\.vercel\.app so only our preview deploys are allowed. --- .env.example | 4 ++-- backend/main.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index 7d06900..2028a86 100644 --- a/.env.example +++ b/.env.example @@ -41,8 +41,8 @@ GITHUB_REDIRECT_URI=http://localhost:3000/auth/github/callback # Comma-separated list of allowed origins ALLOWED_ORIGINS=http://localhost:3000 # Regex for dynamic CORS origins (Vercel preview deploys) -# Set on Railway to allow PR preview URLs to call the backend -# ALLOW_ORIGIN_REGEX=https://.*\.vercel\.app +# Scoped to our project name so only our previews can call the backend +# ALLOW_ORIGIN_REGEX=https://opencodeintel.*\.vercel\.app # Redis (auto-configured in Docker, set REDIS_URL in Railway) REDIS_HOST=redis diff --git a/backend/main.py b/backend/main.py index a466f70..76465c0 100644 --- a/backend/main.py +++ b/backend/main.py @@ -75,8 +75,8 @@ async def dispatch(self, request: Request, call_next): app.add_middleware(RequestSizeLimitMiddleware) ALLOWED_ORIGINS = os.getenv("ALLOWED_ORIGINS", "http://localhost:3000").split(",") -# Allow Vercel preview deploys (dynamic subdomains) so PRs can be tested -# against the production backend without CORS issues +# Allow Vercel preview deploys so PRs can be tested against prod backend. +# Set to project-scoped regex: https://opencodeintel.*\.vercel\.app ALLOW_ORIGIN_REGEX = os.getenv("ALLOW_ORIGIN_REGEX", "") app.add_middleware( CORSMiddleware,