Same-Origin Policy, CORS, and CSP
The browser's default restriction on reading cross-origin responses, how a server relaxes it with CORS, and how CSP restricts what a page can load.
Purpose
The same-origin policy is the browser’s default: a script running on one origin (scheme + host
- port) cannot read response data from a different origin. CORS (Cross-Origin Resource Sharing) is how a server opts specific origins into an exception. CSP (Content-Security-Policy) is a separate mechanism restricting which sources a page is allowed to load scripts, styles, and other resources from.
CORS example
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
A server at https://api.example.com sending these headers permits a page at
https://app.example.com — and only that origin — to read its responses, including when the
request carries credentials (cookies).
CSP example
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.example.com
This restricts the page to only executing scripts from its own origin and one named CDN — even if
untrusted text somehow gets injected as a <script> tag (an XSS attempt), the browser refuses to
execute it if its source isn’t on the allowed list.
Behavior notes
- CORS is enforced by the browser, not the network — a request blocked by CORS typically still
reaches the server; the browser simply withholds the response from the calling script because the
server didn’t grant permission. A non-browser client (
curl, a server-to-server request) has no same-origin policy to enforce and isn’t affected by CORS at all. Access-Control-Allow-Origin: *(any origin) is only valid for requests without credentials; a credentialed request requires naming the exact origin.- CSP is defense-in-depth specifically against the impact of an XSS injection — it doesn’t prevent
the injection itself (proper output encoding/
textContentusage does that), but limits what a successful injection could actually execute.
Common mistakes
- Assuming a CORS error means the request failed on the server — it usually means the server responded, but without the headers needed for the browser to hand that response to the page’s script.
- Treating CSP as a replacement for XSS prevention rather than an additional layer — untrusted text still needs safe rendering (see The Browser and the DOM) regardless of CSP.
Runtime notes
All three are browser enforcement mechanisms defined by web standards (the Fetch standard for CORS, the W3C/WHATWG CSP specification) — none apply to non-browser HTTP clients.