CORS with credentials and a wildcard: the worst combination
What CORS is actually for
By default, a browser stops JavaScript on evil.com from reading responses your API sends to a request — that is the same-origin policy doing its job. CORS (Cross-Origin Resource Sharing) is how your server says 'actually, these specific other origins are allowed to read my responses.' Used correctly, it is a precise guest list.
The trouble starts when the guest list says 'everyone' and the front door also hands out your house keys.
The two ingredients of the bad combination
Two response headers matter here:
Access-Control-Allow-Origin— which sites may read the response.Access-Control-Allow-Credentials: true— whether the browser may send and expose cookies, auth headers and the like on cross-origin requests.
Individually, each is fine. Together, with an open origin, they are the problem. If you allow any origin and also allow credentials, then a malicious site a logged-in user visits can call your API with that user's cookies attached and read the response — their account, their data, through your own authentication.
The wildcard you cannot actually use
Browsers know this is dangerous, so they enforce one rule: you cannot combine a literal Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true. The request fails. Good.
The catch is what developers do to work around that error. To support credentials, the origin must be a specific value — so a common shortcut is to read the incoming Origin header and echo it straight back. That passes the browser check, but it means every origin is allowed, because whatever asks gets approved. You have rebuilt the wildcard, just in a form the browser no longer blocks. This reflected-origin-plus-credentials pattern is the genuinely risky one.
How to configure CORS safely
- Use an explicit allowlist. Keep a fixed set of trusted origins (your own front-ends, known partners) and only reflect an origin back if it is on that list.
- Do not reflect arbitrary origins. If your code copies the request
Origininto the response without checking it, that is the bug. - Only enable credentials when you need them. If the endpoint does not require cookies or auth, leave
Access-Control-Allow-Credentialsoff entirely. - Be specific with methods and headers too, rather than allowing everything by reflex.
- Remember CORS is not authorization. It governs cross-origin reads in browsers; your server must still authenticate and authorize every request on its own.
The honest part
This is an easy one to get wrong, especially when you are fighting a CORS error during development and the fastest fix is to open everything up. That temporary fix has a way of shipping to production and staying there.
Check what your API allows
You cannot see your CORS headers by looking at your site — they live in the responses, not the page. An automated scan inspects the actual Access-Control-* headers your endpoints return and flags an origin policy that is too permissive for the credentials you send. Scan your site and find out whether your API is quietly open to every origin.