Glossary

CORS

Cross-Origin Resource Sharing is the mechanism by which a server tells a browser that another origin is allowed to read its responses. Without it the same-origin policy blocks the read, and the requesting page receives an error even though the request succeeded. It is a relaxation of a browser-enforced restriction, which means it is not access control: a server relying on CORS to keep data private has no protection against anything that is not a browser.

The headers that matter

`Access-Control-Allow-Origin` names the origin permitted to read the response, or `*` for any. Exactly one origin, or the wildcard — a list is not valid.

`Access-Control-Allow-Credentials: true` permits the request to carry cookies and authentication, and the response to be read anyway.

`Access-Control-Allow-Methods` and `Access-Control-Allow-Headers` answer a preflight, stating what the real request may use.

`Access-Control-Expose-Headers` lists which response headers the page may read; by default only a short safe list is available.

`Access-Control-Max-Age` caches the preflight result, avoiding a round trip before every subsequent request.

`Access-Control-Allow-Private-Network` extends the model to requests from a public page into a private network address, which browsers now gate behind an explicit opt-in.

Why the wildcard and credentials conflict

`Access-Control-Allow-Origin: *` with `Access-Control-Allow-Credentials: true` is rejected by browsers, deliberately.

The combination would mean any site could make authenticated requests with the visitor's cookies and read the responses, which is every cross-site attack at once.

Servers wanting credentials must echo a specific origin, which means checking the request's `Origin` header against an allow-list and returning it.

Echoing whatever origin was sent, without checking, is the common implementation of that pattern and is equivalent to the wildcard while appearing to be an allow-list.

Why Vary: Origin is required

A server that returns a different `Access-Control-Allow-Origin` depending on the request's `Origin` is producing a response that varies by that header.

Without `Vary: Origin`, a shared cache stores one response and serves it to requests from other origins, with the wrong permission attached.

The consequence is either a broken integration or, worse, a permission granted to an origin the server never intended.

The header costs nothing and is omitted routinely, which makes it worth checking explicitly on any API behind a CDN.

What CORS is not

It is not authentication or authorisation. The request reached the server and was processed; CORS only decided whether the browser hands the response to the page.

It does not protect an API. Any non-browser client ignores it entirely.

It does not prevent cross-site request forgery. The request is still sent, and a state-changing endpoint is still affected.

A permissive CORS configuration on an endpoint returning personal data is a real finding, because it lets any site read that data using a visitor's own session.

The distinction that resolves most confusion: CORS never stops a request, it stops a read. A logged error about CORS means the server already did whatever the request asked.

Frequently asked questions

Does CORS protect my API?
No. It restricts what browser pages may read. Any client that is not a browser ignores it, so authentication is still required.
Why can I not use a wildcard with credentials?
Browsers reject that combination because it would let any site make authenticated requests with a visitor's cookies and read the responses.
Why do I need Vary: Origin?
Because the response differs by request origin. Without it, a shared cache can serve one origin's permission to a different origin.

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