Same-origin Policy(SOP)

Varsha Chahal
5 min readOct 11, 2023

--

What is Same-origin Policy?

Same-origin Policy is a security mechanism that allows scripts and DOMs on different web pages to access each other’s content only if they have the same origin. SOP is enabled by default in web browsers to prevent websites from stealing information or performing sensitive actions on other websites (different Origin).

“Origin” is an important term when it comes to web application security.

What is an Origin?

An origin comprises of scheme(protocol), hostname(domain) and port number. Ex:

URL: https://example-website.com:443/example/path
Origin: https://example-website.com:443
where,
scheme: ‘https’
domain: ‘example-website.com’
port: ‘443’

If any of the three parameters above is different, they are treated as different origins and disallowed by SOP from reading each other’s contents.
The examples below seem like they are all from the same Origin, but, they are not.

https://example.com:443 ---- http://example.com:443
https://example.com:443 ---- https://example1.com:443
https://example.com:443 ---- https://example.com:8080
https://example.com:443 ---- https://example.ca:443

What Same Origin Policy is not?

SOP is often confused with Content Security Policy(CSP) or even with Cross-origin Resource Sharing(CORS). Content Security Policy is a server-defined header which determines what cross-domain scripts the browser should be allowed to execute in the context of a web page. Cross-origin Resource Sharing is a relaxation of the Same Origin Policy and is implemented using server response headers like Access-Control-Allow-Origin. It instructs browsers to permit other Origins to read the original website’s data.

SOP implementation

Same-origin Policy prevents javascript on one website from reading the contents of another website. However, embedding cross-origin content is usually permitted. For example, you can include an iframe from a different domain on your web page, but you can not read the contents of that embedded iframe. If reading data from the iframe was possible, an attacker could embed a banking website as an iframe on his page, trick the user into performing actions through this website and gain access to all the data they enter on the attacker-controlled bank website.
Different browsers can have different implementations of SOP. For example: Internet Explorer does not include the port number when comparing different origins.

Things SOP allows:

  1. Writing data to a different origin: you can write data to a different origin, but the browser will not allow you to read the response. For example, you can submit forms across domains but are not allowed to read the responses that the server sends back. However, in some cases, you may see pre-flight requests to ensure that you are not affecting the state of the server.
  2. Embedding certain cross-domain HTML elements: <iframe>, <img>, <video>, <audio>, dynamically loaded <scripts>, <object>, <form>, <embed>, <link>. These elements run in the context of the domain in which they are loaded and that domain does not have access to the raw contents of these resources. Some attacks take advantage of the fact that SOP allows the loading of cross-origin elements.

3. fonts applied with @font-face

Exceptions for contents that are accessible by scripts across domains:

  1. some objects are writable but not readable cross-origin. Ex: location object or its location.href property.
  2. some objects are readable but not writable. Ex: window object’s length and close property.
  3. replace function call on the location object is allowed.

How do you allow Cross Origin access then?

SOP is pretty strict when it comes to cross-origin access, you are not even allowed to interact among your subdomains. But there are mechanisms to loosen SOP’s tight grip. Following are some of the techniques:

Cross-origin Resource Sharing(CORS)

This is the most common relaxation technique used for SOP. This is an HTTP mechanism which includes two additional headers when dealing with cross-origin communication, “Origin” and “Access-Control-Allow-Origin”. The browser sends an “Origin” header in a cross-origin HTTP request to check with the server whether it allows this origin, the server replies with “Access-Control-Allow-Origin” stating whether it does. If the origin in the request and response headers do not match, the browser will not allow the web page to read the server’s response or perform certain sensitive actions. When a cross-origin makes requests which are not simple and may include sensitive information, custom headers, different content types, different methods, or have the capability to change a server’s state, the browser might perform a pre-flight request to confirm with the server whether it accepts such requests. There is a danger when a server sets this header to a wildcard ‘*’.

WebSockets

WebSockets don’t fall under the SOP restrictions and the browser will allow cross-origin communications. Browsers still add the Origin header when they see a WebSocket URI being used. The server should compare the origin against its whitelist before allowing it access to any of its resources. To read more about WebSocket security check out my repository here.

document.domain

To allow interactions between two subdomains, document.domain Javascript property can be used. When first.example.com and second.example.com set their document.domain property to example.com the browser will understand that they have the same origin and will allow them to access each other’s contents. The property needs to be set on both domains to ensure access. Note that a domain cannot set its origin to a different domain, it has to follow the domain hierarchy. Ex: first.example.com cannot set its domain to some-bank.com, imagine if that was possible.
But what about the port that makes up the origin too? Setting document.domain property implicitly sets its port to null. No port, no problem. The scheme should still be the same and is not affected by this property.

Cookies and SOP

SOP policies are more relaxed for cookies, they are accessible by subdomains even though they are still different origins. You can set the HttpOnly cookie flag to prevent JavaScript from accessing it. To disallow the browser from sending cookies with cross-domain requests you can use the SameSite flag.

Does SOP protect your website against attacks?

If it’s so strict, it must protect against something. It does protect your websites against a class of CSRF(Cross Site Request Forgery) attacks, but that alone is not enough.
Most kinds of CSRF attacks rely on session cookies to perform sensitive actions and here the attacker does not need to access these cookies via scripts as the browser sends them automatically with a cross-site request. However, SOP can prevent cross sites from accessing the custom headers, CSRF tokens in DOM elements or credentials that you use for CSRF protection. CSRF attacks would be nearly impossible to mitigate without SOP and you should not depend solely on SOP to protect you against them.

What SOP does not protect you against?

SOP will not protect your website against XSS and clickjacking attacks.
Even though SOP will not let cross-origin scripts from accessing your website’s data, if your website is vulnerable to script injection, SOP cannot prevent this script from performing malicious actions.
In the case of clickjacking, the attacker embeds an invisible tool page(via iframe) from a genuine website into their own malicious website, the user is tricked into thinking that they are performing actions on the attacker-controlled website whereas they are actually clicking on the invisible elements thus making requests to the embedded iframe’s backend. it does prevent you from accessing any data within the iframe, but it has no control over what actions are performed within an iframe context.

--

--