CORS misconfiguration — how `Access-Control-Allow-Origin: *` breaks your app
CORS is one of the most misunderstood security headers. Here is exactly when `*` is safe, when it is catastrophic, and how to configure CORS correctly for a Next.js + Supabase stack.
CORS (Cross-Origin Resource Sharing) governs whether a browser at origin A is allowed to read a response from origin B. Misconfiguration ranges from "your API is unusable" to "any website can read your authenticated user's data".
What it is
Browsers enforce the same-origin policy by default — JavaScript on A cannot read responses from B. CORS is the opt-in mechanism where B declares which origins may read its responses. `Access-Control-Allow-Origin: *` means "anyone", `Access-Control-Allow-Origin: https://app.example.com` means "just this origin".
Vulnerable example
// Vulnerable combination:
export async function GET() {
return new Response(JSON.stringify(await getUserProfile()), {
headers: {
"Access-Control-Allow-Origin": "*", // <- anyone can read
"Access-Control-Allow-Credentials": "true", // <- with cookies!
},
});
}
// This combination is REJECTED by browsers, but the mistake pattern keeps coming up.Fixed example
// Fixed: explicit allowlist + credentials
const ALLOWED_ORIGINS = new Set([
"https://app.yourdomain.com",
"https://www.yourdomain.com",
]);
export async function GET(req: Request) {
const origin = req.headers.get("origin") ?? "";
const ok = ALLOWED_ORIGINS.has(origin);
return new Response(JSON.stringify(await getUserProfile()), {
headers: {
"Access-Control-Allow-Origin": ok ? origin : "",
"Access-Control-Allow-Credentials": ok ? "true" : "false",
"Vary": "Origin",
},
});
}How Securie catches it
Securie scans every response-setter in your codebase for CORS headers. Combinations that allow credentialed access from untrusted origins are flagged critical.
Checklist
- Never combine `Access-Control-Allow-Origin: *` with `Access-Control-Allow-Credentials: true`
- Maintain an allowlist of explicit origins; do not echo back the request origin without validating
- Set `Vary: Origin` when the response depends on the request origin (for CDN correctness)
- Preflight responses are short-cached — test with realistic cache settings
- Public APIs (no cookies, no auth headers) may use `*`
FAQ
Is CORS a security feature?
Partially. CORS protects users from cross-site data reads but does not protect your server from any attack. CSRF is a separate concern.