CORS misconfiguration: the wildcard and reflection traps
Cross-Origin Resource Sharing (CORS) controls which other websites can read responses from your API. A wildcard or reflected origin policy can let any site make authenticated requests and read the results.
What it is
Browsers block cross-origin reads by default. CORS headers selectively relax that. Access-Control-Allow-Origin: * opens responses to every website.
A subtler bug is origin reflection: the server echoes whatever Origin the request carried back into the allow-origin header, which effectively trusts everyone while looking specific.
Why it matters
If your API serves user data and allows credentials, an overly broad CORS policy lets a malicious site read a logged-in victim's data straight from your API.
Reflection combined with Access-Control-Allow-Credentials: true is especially dangerous — it defeats the same-origin protection that normally keeps user data private.
How to fix it
Validate the request Origin against a fixed list of trusted domains and only then echo it back.
const ALLOWED = new Set(["https://app.yourdomain.com"]);
const origin = req.headers.get("origin") ?? "";
const allow = ALLOWED.has(origin) ? origin : "";
// only set the header when allow is non-emptyBrowsers forbid Access-Control-Allow-Origin: * together with credentials, so apps sometimes reflect the origin instead — which is the vulnerability. Use a strict allowlist instead.
If an endpoint doesn't need cross-origin access, send no CORS headers at all. Only open the specific routes that genuinely require it.
FAQ
Is Access-Control-Allow-Origin: * always bad?
Not for truly public, non-credentialed resources (e.g. a public font or open data API). It's dangerous for anything tied to a user session.
Does CORS protect my server?
No — CORS is enforced by the browser, not the server. It governs what other sites' JavaScript can read, not whether a request reaches you.
Is your app affected?
AppSafe checks for this and dozens of other issues in one free scan.
Scan my app freeRelated guides
Public GraphQL introspection: why it's a problem and how to turn it off
A single query returns your entire schema. Turn it off in production.
Secure, HttpOnly, and SameSite cookie flags
Three flags that keep session cookies from being stolen.
Dangerous HTTP methods: how TRACE, PUT, and DELETE get advertised
An OPTIONS response that lists TRACE or DELETE tells attackers more than it should.
API keys exposed in client-side JavaScript
Anything in your bundle is public. Treat it that way.