Securityerror: Blocked a Frame With Origin from Accessing a Cross-Origin Frame

SecurityError: Blocked a frame with origin from accessing a cross-origin frame

Same-origin policy

You can't access an <iframe> with different origin using JavaScript, it would be a huge security flaw if you could do it. For the same-origin policy browsers block scripts trying to access a frame with a different origin.

Origin is considered different if at least one of the following parts of the address isn't maintained:

protocol://hostname:port/...

Protocol, hostname and port must be the same of your domain if you want to access a frame.

NOTE: Internet Explorer is known to not strictly follow this rule, see here for details.

Examples

Here's what would happen trying to access the following URLs from http://www.example.com/home/index.html

URL                                             RESULT
http://www.example.com/home/other.html -> Success
http://www.example.com/dir/inner/another.php -> Success
http://www.example.com:80 -> Success (default port for HTTP)
http://www.example.com:2251 -> Failure: different port
http://data.example.com/dir/other.html -> Failure: different hostname
https://www.example.com/home/index.html:80 -> Failure: different protocol
ftp://www.example.com:21 -> Failure: different protocol & port
https://google.com/search?q=james+bond -> Failure: different protocol, port & hostname
Workaround

Even though same-origin policy blocks scripts from accessing the content of sites with a different origin, if you own both the pages, you can work around this problem using window.postMessage and its relative message event to send messages between the two pages, like this:

  • In your main page:

    const frame = document.getElementById('your-frame-id');
    frame.contentWindow.postMessage(/*any variable or object here*/, 'http://your-second-site.example');

    The second argument to postMessage() can be '*' to indicate no preference about the origin of the destination. A target origin should always be provided when possible, to avoid disclosing the data you send to any other site.

  • In your <iframe> (contained in the main page):

    window.addEventListener('message', event => {
    // IMPORTANT: check the origin of the data!
    if (event.origin.startsWith('http://your-first-site.example')) {
    // The data was sent from your site.
    // Data sent with postMessage is stored in event.data:
    console.log(event.data);
    } else {
    // The data was NOT sent from your site!
    // Be careful! Do not use it. This else branch is
    // here just for clarity, you usually shouldn't need it.
    return;
    }
    });

This method can be applied in both directions, creating a listener in the main page too, and receiving responses from the frame. The same logic can also be implemented in pop-ups and basically any new window generated by the main page (e.g. using window.open()) as well, without any difference.

Disabling same-origin policy in your browser

There already are some good answers about this topic (I just found them googling), so, for the browsers where this is possible, I'll link the relative answer. However, please remember that disabling the same-origin policy will only affect your browser. Also, running a browser with same-origin security settings disabled grants any website access to cross-origin resources, so it's very unsafe and should NEVER be done if you do not know exactly what you are doing (e.g. development purposes).

  • Google Chrome
  • Mozilla Firefox
  • Safari
  • Opera: same as Chrome
  • Microsoft Edge: same as Chrome
  • Brave: same as Chrome
  • Microsoft Edge (old non-Chromium version): not possible
  • Microsoft Internet Explorer

SCORM: SecurityError: Blocked a frame with origin from accessing a cross-origin frame FOR SAME ORIGIN

The issue has been resolved, and it is specific to the SCORM protocol.

When you open a piece of SCORM content, which is a bunch of html,flash,js and other media files, the first thing it does is trying to find the SCORM api.

The SCORM api is JS that has to be in the window that loads the SCORM content.

In some SCORM packages, the function that looks for the API, looks recursively for the TOP window, i.e. the initial window that started the entire process.

In my case it was a window on my site, that poped the SCORM launcher on my CDN, which has a different domain name.

All I had to do to solve this issue, is cheat the browser to think the SCORM launcher (the window I poped on the CDN) is the TOP, by adding the following two js lines in it:

window.top=window;
window.opener=window;

Uncaught DOMException: Blocked a frame with origin "http://localhost:8080" from accessing a cross-origin frame while listing the iframes in page

This error message...

Uncaught DOMException: Blocked a frame with origin "http://localhost:8080" from accessing a cross-origin frame.

...implies that the WebDriver instance blocked from accessing a cross-origin frame.


Same-origin policy

Same-origin policy : Same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. It is a critical security mechanism for isolating potentially malicious documents.


Cross-Origin Resource Sharing (CORS)

Cross-Origin Resource Sharing (CORS) : Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a Browser Client to let the AUT (Application under Test) running at one origin (domain) have permission to access selected resources from a server at a different origin. A web application makes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, and port) than its own origin.


Example of an origin

Here is an example of origin comparisons to the URL http://store.company.com/dir/page.html

URL                                                  Outcome    Reason
http://store.company.com/dir2/other.html Success
http://store.company.com/dir/inner/another.html Success
https://store.company.com/secure.html Failure Different protocol
http://store.company.com:81/dir/etc.html Failure Different port
http://news.company.com/dir/other.html Failure Different host

What went wrong

When you tried to loop through frames your script/program tried to access an <iframe> with different origin using JavaScript which would been a huge security flaw if you would have achieved it. As mentioned above the same-origin policy browsers block scripts trying to access a <iframe> with a different origin.

Two pages have the same origin if the protocol, port (if one is specified), and host are the same for both the webpages. You'll see this referred to as the "scheme/host/port tuple" at times (where a "tuple" is a set of three components that together comprise a whole). Perhaps the protocol, domain, hostname and port must be the same of your same domain when you want to access the desired frame.

Solution

The AUT may contain numerous frames / iframes and some of them may be loaded only after certain JavaScript / Ajax have completed where as some of them may be having style attribute set as display:none; or visiblity as hidden. Of-course won't require to interact with all of them. So it will be a better approach to identify the attributes of the <iframe> and switch accordingly. You can switch to an <iframe> through:

  • Frame Name
  • Frame ID
  • Frame Index
  • WebElement

As per best practices when you intent to switch to a frame induce WebDriverWait for frameToBeAvailableAndSwitchToIt as per the references below.

Here you can find a relevant discussion on Uncaught DOMException


References

Some references:

  • In this discussion you will find a detailed analysis on SecurityError: Blocked a frame with origin from accessing a cross-origin frame

  • In this discussion you will find the different approaches on Is it possible to switch to an element in a frame without using driver.switchTo().frame(“frameName”) in Selenium Webdriver Java?

  • In the A Better Approach to Switch Frames section of this discussion you will find the different approaches on How can I select a html element no matter what frame it is in in selenium?

Uncaught SecurityError: Blocked a frame with origin ... from accessing a frame with origin

I've finally found a solution.

The top of my iframe had a domain.location set to domain.com and my iframe a domain.location set to support.domain.com.

Event though I still think that both belong to the same domain, browsers don't like it it seems so.

Re-setting the domain.location did the work.

To answer the ones asking about how to re-set location.domain, here is the snippet of code my team used to use. This is quite old (2y ago), not really optimized and we do not use it anymore, but I guess it's worth sharing.
Basically, what we were doing is load the iframe with passing it top domain in the URL parameters.

var topDomain = (function handleDomain(parameters) {
if (typeof parameters === "undefined") {
return;
}
parameters = parameters.split("&");
var parameter = [],
domain;
for (var i = 0; i<parameters.length; ++i) {
parameter.push(parameters[i]);
}
for (var j = 0; j<parameter.length; ++j) {
if (parameter[j].indexOf("domain") > -1) {
domain = parameter[j];
break;
}
}
if (typeof domain !== "undefined") {
domain = domain.split("=");
return domain[1];
}
return;
})(window.location.search),
domain = document.domain;

if (domain.indexOf(topDomain) > -1 && domain !== topDomain) {
document.domain = topDomain;
}

JavaScript document.domain Uncaught DOMException: Blocked a frame with origin

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



Related Topics



Leave a reply



Submit