While I was testing the SOP, i came to this scenario two documents has a relationship with the same domain as i would expected and it throws an error when i try to get the location.
To reproduce the problem:
- Open https://www.google.com
- from the console
let opened = window.open("https://www.google.com")
- from the same window do
opened.location.toString()
which will return the correct location
- from the second tab's console do
document.domain = "www.google.com"
from the first tab do opened.location.toString()
and you will get an error
Uncaught DOMException: Blocked a frame with origin "https://www.google.com" from accessing a cross-origin frame.
at <anonymous>:1:12
Can anyone explain this strange behavior?
This error is not a bug. The same-origin policy is a security mechanism that ensures that window objects only have access to the informations they are authorized to get. In your case, this includes having access to opened.location
.
Upon creation, both tabs have the same origin, which allows the first one to access opened.location
. But after the call to document.domain='www.google.com'
, they don't anymore.
"What? But in both tabs, window.location.origin
are identical"
Yes, but it is a little bit more complex. The origin is defined by the scheme/host/port tuple, see @TheUnknown's answer for more details. The scheme and host stay the same all along, and they're the one included in the string of window.location.origin
.
The tricky thing to know is that any call to document.domain
, including document.domain = document.domain
, causes the port number to be overwritten with null
, therefore causing a difference in the two tabs' origins, and preventing them from communicating informations like opened.location
with one another, thus the error.
Informations extracted from MDN's guide on same-origin policy
First, I would recommend, you read Same-origin Policy.
The same-origin policy is a critical security mechanism that restricts
how a document or script loaded from one origin can interact with a
resource from another origin. It helps isolate potentially malicious
documents, reducing possible attack vectors.
Two URLs have the same origin if the protocol, port (if specified), and host are the same for both. You may see this referenced as the "scheme/host/port tuple", or just "tuple". (A "tuple" is a set of items that together comprise a whole — a generic form for double/triple/quadruple/quintuple/etc.)
In this particular case, you open a window with HTTPS protocol, however when you set the domain, the protocol is changed to HTTP, see image below:
As per 1, if the protocols are not the same, then its a violation of the principle and hence you get the error
Uncaught DOMException: Blocked a frame with origin
"https://www.google.com" from accessing a cross-origin frame.
cross-origin is the keyword here.
Also, check out this SecurityError: Blocked a frame with origin from accessing a cross-origin frame for more details.
This will be a bit uninformative (just states facts), nevertheless:
After you change domain
in window B, window B stops accounting window A as opener
.
Since window A is no longer considered an opener of window B, the access is prohibited.
This makes me think, that altering document.domain
is considered potentially insecure and is "punished" by orphaning the child window.