I have an sandboxed iframe that doesn't allow changing location:
<iframe sandbox="allow-forms allow-popups allow-pointer-lock allow-same-origin allow-scripts" class="iframe visible" src="thesource.html" width="100%" scrolling="auto" frameborder="0"></iframe>
If the iframe tries to unframe itself or change location I see a blank page because the browser stops the iframe's operation. This is the log from Chrome:
Unsafe JavaScript attempt to initiate navigation for frame with URL 'http://example.com' from frame with URL 'http://otherdomaian.com'. The frame attempting navigation of the top-level window is sandboxed, but the 'allow-top-navigation' flag is not set.
That is great but I want to catch this so if it happens I'll move to the next iframe. So how do I catch this attempt?
EDIT:
I added a jsfiddle code (check the error in the console log)
I also tried to listen for an event with no success:
document.addEventListener('error', receiveMessage, true);
function receiveMessage(error) {
alert("iframe tried to unframe itself");
}
Correct Option: A. Scripts are re-enabled by allow-scripts. The sandbox attribute enables an extra set of restrictions for the content in the iframe. Allow-forms re-enables from submission.
Given an iframe with an empty sandbox attribute, the framed document will be fully sandboxed, subjecting it to the following restrictions: JavaScript will not execute in the framed document. This not only includes JavaScript explicitly loaded via script tags, but also inline event handlers and javascript: URLs.
Note that it's not advisable to add both values allow-scripts and allow-same-origin: these two values will allow the iframe to access and modify your DOM. In this case, a malicious iframe could perform all sorts of operations, and could even remove its own sandbox attribute!
Now, these are things that have a great security risk, so to make things more secure for the users, W3C added the 'Sandbox' attribute in the HTML specifications. This attribute limits the action from an iframe within a web page and makes it quite secure and protected.
I am new here so I don't have enough reputation to comment on answers and I apologize if I am doing this wrong, but the accepted solution will unfortunately not be able to accomplish what you are looking for.
I was able to demonstrate what I mean by having the script from the JSFiddle above run once the DOM is ready (there will be no alert but still an error in the console). Here's a little more detail on what happens currently with that fiddle:
// running with the No wrap - in <head> option
var frame = document.querySelector('iframe'); // null, the iframe isn't there yet
try {
frame.src="http://wedesignthemes.com/themes/redirect.php?theme=wedding";
} catch(e) {
// TypeError here, no hints about the iframe :(
alert('Error!');
}
The exception that is being caught has nothing to do with the iframe, it is actually a type error from trying to set the src
property on a null
value.
What you really want to do is catch the error inside of the iframe (when the sandboxed script tries to access window.top
), but this is not possible because of the Same-origin policy. Btw, setting the "allow-same-origin"
sandbox flag only has any effect when the iframe content is being served from the same origin
as the top level document. E.g. as soon as the src
or location
of the iframe is changed to a different origin
, there's no way to touch anything inside.
There are ways to communicate across iframe
boundaries, such as with window.postMessage
or the older and hackier way of using the iframe's location.hash
, but I am assuming you can't affect the source of the page going into your iframe. (A nice developer would of course be open to suggestions and see that a feature like this could be useful.)
The only way that I was able to catch this error without violating any browser security policies was to set the allow-top-navigation
sandbox flag and then use the window.onbeforeunload
handler in the top level document to catch the navigation attempt from the child iframe
. I would never recommend this because the user experience is awful. There is no way to prevent the navigation without prompting the user about whether they want to leave the page or not. Proof of concept below:
<iframe id="myframe" sandbox="allow-scripts allow-top-navigation"></iframe>
<script>
var url = "http://wedesignthemes.com/themes/redirect.php?theme=wedding",
frame = document.getElementById("myframe"),
listener;
listener = window.addEventListener("beforeunload", function(e) {
e.preventDefault();
e.stopImmediatePropagation();
// The iframe tried to bust out!
window.removeEventListener("beforeunload", listener);
return "This is unavoidable, you cannot shortcut a " +
"navigation attempt without prompting the user";
});
frame.src = url;
</script>
So unfortunately I can't find any ways to do this nicely in current browser implementations without help from your 3rd party content developer. I read some interesting things in the HTML5 spec that might allow us to do things like this in the future (and am unfortunately maxed out on my number of links I can insert here), so I would keep an eye out as things progress.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With