Glossary
Cross-Origin Resource Sharing

Cross-Origin Resource Sharing

Alex Khazanovich

Your web app runs on app.example.com and calls an API on another subdomain. To a browser, those are different origins, and by default a page cannot read responses from another origin. Cross-Origin Resource Sharing (CORS) is how the API tells the browser which other origins may read its responses.

Key Takeaways

  • CORS is a browser mechanism that relaxes the same-origin policy for origins a server explicitly allows.
  • JSON bodies, custom headers and methods like PUT trigger a preflight request first.
  • Most CORS errors come from missing, duplicated or wrongly cached Access-Control-Allow-Origin headers.
  • When the allowed origin changes per request, CDNs must cache a separate copy per origin.

What Is Cross-Origin Resource Sharing?

Under the same-origin policy, two URLs share an origin only when their scheme, host and port all match. The policy stops a malicious site from reading your account pages through a logged-in browser. Cross-Origin Resource Sharing is an opt-in exception: the server sends Access-Control response headers, and the browser lets the page read the response only if they allow its origin. CORS is defined in the WHATWG Fetch Standard.

{{cool-component}}

How CORS Works: Preflight Requests and Response Headers

For some requests, the browser first sends a preflight request: an OPTIONS call carrying Access-Control-Request-Method and, if needed, Access-Control-Request-Headers. The server must answer with a 2xx status and headers such as:

  • Access-Control-Allow-Origin: one origin or *, never a list
  • Access-Control-Allow-Methods and Access-Control-Allow-Headers
  • Access-Control-Allow-Credentials: true, when cookies are sent
  • Access-Control-Max-Age, capped at 2 hours in Chrome and 24 hours in Firefox

If the preflight passes, the browser sends the real request.

Common CORS Errors and What Causes Them

Chrome logs each CORS error as "blocked by CORS policy", followed by the reason:

  • "No 'Access-Control-Allow-Origin' header is present": the server, or an error page, left it out.
  • Wildcard with credentials: * is not allowed when the request includes cookies.
  • "Response to preflight request doesn't pass access control check": OPTIONS returned a non-2xx status, often because authentication ran on it, or the server redirected it.
  • "The 'Access-Control-Allow-Origin' header contains multiple values": both the CDN and the origin added it.
  • "Not equal to the supplied origin": a cache served a response meant for another origin.

How CDNs Affect CORS Behavior

A CDN can cache, strip or add CORS headers. If your origin echoes the request's Origin back in Access-Control-Allow-Origin, the response differs per origin, so it needs a Vary header of Origin or Origin in the cache key. Providers behave differently: CloudFront leaves Origin out of its cache key unless you forward it, Cloudflare adds Origin to its cache key, and Fastly stores one copy per origin when you send Vary: Origin. Most CDNs don't cache OPTIONS responses by default.

{{cool-component}}

CORS Configuration Best Practices for API and CDN Environments

  • Use an exact-match allowlist of origins, and never trust null.
  • Send Vary: Origin only when the allowed origin changes per request.
  • Answer OPTIONS with a 2xx and skip authentication on it.
  • Set CORS headers in one layer, CDN or origin, not both.
  • Keep rules identical on every CDN you use, and watch CDN logs for failed preflights.

Conclusion

CORS is simple in principle: the server lists who may read its responses, and the browser enforces the list. Most problems come from caching and duplicated headers, so CDN settings deserve as much review as application code, alongside the other security risks for CDN operations.

FAQs

Why Does CORS Not Apply to Server-to-Server Requests?

CORS is enforced by browsers to protect users' sessions, not by servers. A backend service, curl or a script can call any API regardless of CORS headers, because no logged-in user's cookies are at risk. That is also why CORS is not access control: protect APIs with authentication.

When Is the Access-Control-Allow-Origin Wildcard Unsafe?

A wildcard is fine for public data such as fonts or open APIs. It is unsafe when a resource relies on network location for protection, such as intranet services or IP-allowlisted APIs, because any website could make a visitor's browser read them. Browsers already reject the wildcard on requests that send cookies.

How Does CDN Caching Break CORS When Misconfigured?

If the origin returns a different Access-Control-Allow-Origin per requesting site, the CDN must keep a separate copy per origin. Without Vary: Origin or Origin in the cache key, it serves the first cached header to everyone, and other sites get "not equal to the supplied origin" errors until the cache expires.

How Do Simple and Non-Simple CORS Requests Differ?

Simple requests use GET, HEAD or POST with only safelisted headers and a form or plain text content type, so the browser sends them directly. Anything else, such as PUT, a JSON content type or an Authorization header, triggers a preflight first. The Fetch Standard now calls these CORS-preflight requests.

Can CORS Misconfiguration Create a Security Vulnerability?

Yes. The classic flaw reflects any Origin while allowing credentials, letting any website read a logged-in user's data. PortSwigger's 2016 research showed a bitcoin exchange leaking users' API keys this way. Trusting the null origin, matching origins by prefix or suffix, and trusting vulnerable subdomains cause similar leaks.

Published on:
October 26, 2026

Related Glossary

See All Terms
This is some text inside of a div block.