[Security] Block cross-origin account enumeration by removing wildcard CORS#459
Conversation
cors('*') allowed any cross-origin script to call /api/auth/signup
and read the full response, making it trivial to probe thousands of
emails and determine which are registered from the 400 vs 201 status.
Replace with an origin allowlist driven by ALLOWED_ORIGINS so only
the known frontend origin can read API responses. Add credentials:true
so session cookies flow correctly from the allowlisted frontend.
Fixes GitMetricsLab#446
✅ Deploy Preview for github-spy ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Warning Review limit reached
Your plan currently allows 1 review/hour. Refill in 43 minutes and 21 seconds. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more review capacity refills, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@mehul-m-prajapati why was my code not merged? did i make any mistakes in my code? please let me know |
Problem
backend/server.jsappliedapp.use(cors('*'))globally. This allowed JavaScript running on any origin to callPOST /api/auth/signupand read the full response body — no browser restriction applied.Concrete attack:
An attacker could automate this across millions of email addresses in minutes, building a full map of registered accounts with zero rate-limit bypass required. Those accounts could then be targeted for phishing or credential stuffing. Additionally, any future authenticated endpoint is exposed by default the moment it is added — the wildcard is a permanent silent grant.
Changes
backend/server.jscors('*').process.env.ALLOWED_ORIGINS(comma-separated), defaulting tohttp://localhost:5173.credentials: trueso session cookies flow correctly from the allowlisted frontend.Originheader) pass through unchanged.backend/.env.sampleALLOWED_ORIGINS=http://localhost:5173so all contributors know to configure this for their deployment environment.Why this approach fixes the root cause
The wildcard was a blanket grant at the infrastructure level — any fix to individual routes would be incomplete because the problem recurs for every new endpoint. Replacing it with an env-var-driven allowlist means the trusted origin set is explicit, per-environment, and auditable. A cross-origin probe from an unlisted origin now receives a CORS error and cannot read the response.
Steps to test
.env(ALLOWED_ORIGINS=http://localhost:5173).http://localhost:5173,POST /api/auth/signup— succeeds (allowlisted).http://localhost:5174and repeat — browser blocks with CORS error, response is unreadable.Access-Control-Allow-Originin the response header showshttp://localhost:5173, not*.curl -X POST http://localhost:5000/api/auth/signup ...(no Origin header) — still works for server-to-server calls.http://localhost:5174toALLOWED_ORIGINS, restart — both ports accepted.Edge cases covered
Originheader (curl, health checks, internal tooling) — allowed via the!originguard.ALLOWED_ORIGINS.credentials: trueensures cookies flow from the allowlisted frontend.Regression check
No route handlers, session logic, validators, or tests were changed. All existing endpoints continue to work normally from
http://localhost:5173. The only behaviour change is that requests from non-allowlisted origins are now rejected by the browser.Please review and merge this under GSSoC 2026.