What Is the Same-Origin Policy?

On this page
  1. Why does the web need a same-origin policy?
  2. What exactly counts as an origin?
  3. What does the policy actually block?
  4. How does CORS relax the policy safely?
  5. Where does the same-origin policy fail you?

The same-origin policy is the browser rule that stops JavaScript on one website from reading data that belongs to another. An origin is the exact combination of scheme, host, and port; if any of the three differ, the browser treats the two contexts as strangers. It is the foundation the rest of web security is built on.

Why does the web need a same-origin policy?#

Your browser is one process holding sessions for your bank, your email, and a tab of random links. Without an isolation rule, any page could quietly fire a request to your bank — riding on your logged-in cookies — and read the response. The same-origin policy is what makes having twenty tabs open survivable: pages can request a lot, but they can only read what their own origin owns.

That distinction — sending versus reading — explains most of the confusing edge cases. A page can embed an image from anywhere, submit a form to anywhere, even send a fetch() to anywhere. What it cannot do, by default, is read the bytes that come back from a different origin.

What exactly counts as an origin?#

An origin is the tuple scheme + host + port, compared character-for-character. There is no “close enough”:

URL AURL BSame origin?Why
https://example.com/ahttps://example.com/b/cYesPath is ignored
https://example.comhttp://example.comNoScheme differs
https://example.comhttps://app.example.comNoHost differs
https://example.comhttps://example.com:8443NoPort differs
https://example.com:443https://example.comYes443 is the HTTPS default

What does the policy actually block?#

The same-origin policy governs read access between browsing contexts and responses. In practice, cross-origin JavaScript cannot:

  1. Read the DOM of a window or iframe from another origin.
  2. Read the response body of a fetch()/XMLHttpRequest to another origin (unless CORS allows it).
  3. Read another origin’s cookies, localStorage, or IndexedDB.

What it deliberately does not block: embedding cross-origin images, styles, and scripts; navigating to other origins; and submitting forms cross-origin. The web’s openness and its biggest quirks both live in that gap — cross-site request forgery exists precisely because sending was left open.

How does CORS relax the policy safely?#

Cross-Origin Resource Sharing is the server’s way of saying “these specific strangers may read me.” The server — the owner of the data — opts in via response headers:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Vary: Origin

The browser enforces the contract: if the requesting origin is not on the list, the response is fetched but never handed to the page’s JavaScript. Two rules keep CORS deployments safe:

  1. Never reflect the request’s Origin header back blindly — that is equivalent to * with credentials.
  2. Treat Access-Control-Allow-Credentials: true as a loaded weapon; combine it only with an exact-match allowlist.

Where does the same-origin policy fail you?#

The policy protects origins from each other. It cannot protect an origin from itself. If an attacker gets script injected into your page — the attack class covered in our cross-site scripting deep dive — that script is same-origin, and SOP grants it everything. This is why defense in depth pairs SOP with output encoding, a Content Security Policy, and the security headers that harden the browser’s defaults.

For the full context of where this rule sits in the web security stack, start at the Web Security hub.

Frequently asked questions#

Is the same-origin policy the same thing as CORS?

No. The same-origin policy is the default restriction; CORS is the controlled mechanism for relaxing it. CORS headers let a server declare which other origins may read its responses. Without CORS, the same-origin policy simply applies in full.

Does the same-origin policy stop all cross-site attacks?

No. It stops cross-origin reading of responses, but requests can still be sent cross-origin, which is why CSRF exists. And if an attacker injects script into your page via XSS, their code runs same-origin and SOP offers no protection at all.

Are two subdomains of the same site the same origin?

No. https://app.example.com and https://api.example.com are different origins because the host differs. Origins compare the exact scheme, host, and port. Subdomain relationships matter for cookies, but not for the same-origin policy itself.

Sources & further reading