Same-origin Policy

The Same‑Origin Policy (SOP) is the first line of defense in modern browsers. It defines a strict boundary that prevents scripts loaded from one web origin from accessing resources belonging to another. By enforcing this rule, browsers protect users from malicious sites that might try to read sensitive data such as cookies, local storage, or the contents of a page they do not own.

What Makes Two URLs the Same Origin?

Two URLs are considered the same origin only when all three of the following components match exactly:

Component Description
Protocol The scheme (http, https, ftp, etc.)
Domain The host name or IP address
Port The network port number (default ports are implied if omitted)

If any one of these differs, the URLs are treated as cross‑origin. The path portion of the URL is irrelevant; /home and /about are still the same origin if the protocol, domain, and port are identical.

Example
https://www.example.com/page.html and https://www.example.com/other.html are same‑origin.
http://www.example.com/other.html is cross‑origin because the protocol differs.
https://api.example.com/data is cross‑origin due to a different domain.
https://www.example.com:8080/api is cross‑origin because the port is different.

What the Policy Restricts

When a script runs in a browser, it is automatically confined to its origin. Without explicit permission, the following cross‑origin actions are blocked:

  1. DOM Access – Scripts cannot read or manipulate the Document Object Model of a page loaded from another origin, even if it is embedded via an <iframe>.
  2. Storage Access – Cookies, localStorage, sessionStorage, and IndexedDB data belonging to a different origin are inaccessible.
  3. Response Reading – While a browser will allow a cross‑origin request to be sent (e.g., via fetch or XMLHttpRequest), the response body is opaque to the calling script unless the server explicitly grants permission.

It is important to note that SOP does not block the sending of requests. It only blocks the reading of responses. Resources such as images, scripts, and stylesheets are still fetched from other origins; this is why techniques like JSONP were historically viable.

Why SOP Matters

Consider a scenario where a user is logged into their banking site. The browser stores a session cookie that authenticates the user. If a malicious site could freely read responses from the bank’s domain, it could impersonate the user, check balances, or initiate transfers. SOP stops the malicious script from accessing the bank’s data, thereby preventing such credential‑stealing attacks.

In essence, SOP enforces a trust boundary around each origin, ensuring that only code from the same origin can interact with its resources. This boundary is the foundation upon which many other security mechanisms are built.

Legitimate Ways to Communicate Across Origins

In modern web development, cross‑origin interactions are common: front‑end applications often consume APIs hosted on different domains, or embed third‑party widgets. Several standardized methods allow developers to bypass SOP safely:

1. Cross‑Origin Resource Sharing (CORS)

CORS is the de‑facto standard for cross‑origin requests. The server includes specific HTTP headers to declare which origins are allowed to read its responses:

Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Credentials: true

When a browser sees these headers, it lifts the SOP restriction for that response. For “non‑simple” requests—those that use methods other than GET/HEAD/POST, or that include custom headers—the browser first sends an OPTIONS preflight request to verify permissions.

2. JSONP (Legacy)

JSONP exploits the fact that <script> tags are exempt from SOP. The server returns JavaScript code that calls a callback function supplied by the client. Because only GET requests are possible, JSONP is limited and carries security risks. Modern developers prefer CORS, but JSONP may still be encountered in legacy systems.

3. postMessage

For communication between windows or frames that originate from different domains, the Window.postMessage API provides a secure channel:

// Parent page sends a message to an iframe
iframe.contentWindow.postMessage('hello', 'https://child.example.com');

// Child iframe receives the message
window.addEventListener('message', event => {
  if (event.origin !== 'https://parent.example.com') return;
  console.log(event.data);
});

postMessage allows arbitrary data to be exchanged while still enforcing origin checks, making it ideal for cross‑origin messaging.

4. Server‑Side Proxy

A common pattern is to route all external requests through a server that shares the same origin as the front end. The browser talks to the proxy, which then forwards the request to the target API. Because the proxy is on the same origin, SOP is never triggered. This approach also gives developers full control over request headers, authentication, and caching.

Summary

The Same‑Origin Policy is a cornerstone of web security, defined by the trio of protocol, domain, and port. It blocks scripts from reading or manipulating data across origins, thereby preventing a wide range of attacks such as credential theft and data exfiltration. While SOP is restrictive, it can be safely circumvented using standardized techniques like CORS, postMessage, and server‑side proxies. Mastery of these tools is essential for any web developer working in today’s distributed, API‑driven ecosystem.