Website problems

CORS wildcard with credentials

A response that allows any origin while also allowing credentials is rejected by every browser. The specification forbids the combination, so the cross-origin call fails no matter what the server intended — and it fails in the browser rather than at the server, which makes it invisible in an API client. Its presence usually means the CORS layer was configured by trial and error until something worked, which is worth reviewing beyond this one pairing.

Why the combination is forbidden

A wildcard says any website may read this response. Credentials mean the request carries the visitor's cookies or authentication.

Together they would let any website make authenticated requests as your visitors and read the answers.

So the specification requires the server to echo one specific origin whenever credentials are allowed, rather than a wildcard.

Browsers enforce it by refusing the response outright, which is the correct behaviour and the reason the call fails.

The server is unaffected: it processed the request and returned a response. Only the browser refuses to hand it to the script.

Why it is invisible in an API client

CORS is a browser rule, not a server rule. Nothing about the response changes for a client that does not enforce it.

So the same request succeeds from a terminal and fails in a page, which is the most common way this is reported.

The browser console names the reason, which is the fastest diagnosis available and the one people skip.

The network panel shows the request completing with a 200, which reinforces the impression that the server is fine — it is.

Which is why the finding is worth stating plainly: the pairing is invalid, not marginal.

What to do instead

Maintain an allow-list of the origins that genuinely need authenticated cross-origin access.

On each request, compare the Origin header against that list and echo it back when it matches.

Send `Vary: Origin` alongside, or a shared cache will serve one origin's response to another.

Where the data is public and no credentials are needed, keep the wildcard and remove the credentials flag — that combination is correct and common.

Never echo the origin without validating it: that is a wildcard written the long way, and it re-creates exactly what the rule forbids.

What the pairing usually indicates

A configuration arrived at by loosening settings until a call worked, rather than from a decision about who should have access.

Which means the rest of the CORS configuration is worth reading: the allowed methods, the allowed headers, and whether the preflight answer matches the real response.

A preflight permitting more than the actual request needs is the same instinct applied elsewhere.

So is a CORS layer added at two places — a framework middleware and a proxy — where the headers now depend on which one ran last.

Reading the whole configuration once is usually quicker than fixing the pairing and returning to the next symptom.

How to check it yourself

`curl -I -H 'Origin: https://example.org' https://api.example.com/endpoint` and read the response headers.

A wildcard allow-origin alongside an allow-credentials value of true is the finding.

Send an OPTIONS request with the same Origin header to see how the preflight is answered.

Compare what the preflight permits against what the real request sends, since a mismatch fails the same way for a different reason.

Test from a browser page rather than only from a terminal, because the terminal will never reproduce the failure.

How VeriFixScan detects it

`api.cors.credentials` detects the invalid wildcard-plus-credentials combination, which is this problem directly.

`api.cors.wildcard` reads the allow-origin policy really returned, so a legitimate public wildcard is distinguished from this pairing.

`api.cors.vary` checks for `Vary: Origin` wherever the origin is echoed, which is the cache consequence of the correct fix.

`api.options.preflight` sends one standards-compliant OPTIONS request and records the answer.

Only endpoints already discovered are tested, so this never widens the surface it examines.

Why testing from outside finds it

CORS headers are frequently produced in more than one place — a framework middleware, a reverse proxy, a CDN rule.

The value that reaches the browser is whichever layer wrote it last.

Reading a configuration file tells you what one layer intends; requesting the endpoint tells you what all of them together produced.

Which is also why an endpoint can behave differently in staging and production with identical application code.

Frequently asked questions

Is a wildcard origin always wrong?
No. For public data with no credentials it is correct and common. It becomes invalid only when credentials are allowed alongside it, which browsers reject outright.
Why does it work in my API client but not in the browser?
CORS is enforced by browsers, not servers. The server answers identically in both cases; only the browser refuses to hand the response to your script.
Can I just echo whatever origin asks?
That is a wildcard written the long way and re-creates the problem. Validate the origin against an allow-list before echoing it, and send Vary: Origin alongside.

Sources

Related

VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.

Scan a website