I'm trying to figure out if it's possible to programmatically change the value of sandbox for an iFrame.
From MDN iframe:
When the embedded document has the same origin as the main page, it is
strongly discouraged to use both allow-scripts and allow-same-origin
at the same time, as that allows the embedded document to
programmatically remove the sandbox attribute. Although it is
accepted, this case is no more secure than not using the sandbox
attribute.
However, changing the attribute in the parent does not successfully trigger sandboxing as that would imply in the child.
document.getElementById('myFrame').setAttribute('sandbox', 'allow-scripts');
The page loaded in that iFrame can successfully gain access to the parent, which would not be the case if sandboxing was working. The attribute does change, but the security is flawed as it does not prevent access to the patent.
console.log(window.parent.document);
The above still works in the iFrame which had the sandbox "programmatically" enabled. This is the case in both Chrome and Firefox, which would imply either intended undocumented functionality or a poorly implemented specification.
Anyone have any ideas on what would be the appropriate expectation?
Please try this fiddle : http://jsfiddle.net/yAwxy/
It's not working when the script is runned onLoad b/c the iframe is already working.
If you try onDomready, the sandboxing is applied b/c the script didn't run yet.
If you log using this fiddle:
<iframe id="myFrame" srcdoc="<script>console.log('Executing script inside iFrame')</script>">
</iframe>
And in the script
console.log('Executing script inside page')
When the script console.log('Executing script inside page') is wrapped onLoad, the outpu is :
Executing script inside iFrame
Executing script inside page
And when wrapped onDomready :
Executing script inside page
Executing script inside iFrame
See also http://jsfiddle.net/yAwxy/1/.
So to change the rules, they must be changed OndomReady
I am running into similar issues when trying to dynamically create iframe contents in Internet Explorer inside of a sandboxed iframe. I tried doing the same thing you did with using javascript to add the sandbox attribute after the iframe was already created and content placed in the iframe (using a javascript: URI in the src= attribute) but the iframe appears to keep it's attributes that were present at the time of being loaded in the page.
Internet Explorer does appear to work differently than FireFox or Chrome when it comes to applying the sandbox attribute. Chrome and FireFox will allow the contents to be dynamically created using src=javascript:function() when the sandbox="allow-scripts" is set. IE appears to apply the unique domain from the sandbox attribute during creation and considers src=javascript:function() to be not-same-origin and will not allow the dynamic creation of the iframe contents.
I am not sure why you are trying to add the sandbox attribute programmatically, but if it is an issue of trying to just load an iframe with dynamic source you can use the srcdoc attribute as well as the sandbox attribute with the only issue being that IE does not support the srcdoc attribute.
To answer your question, I do not believe it is possible to load an iframe and its contents and then add the sandbox attribute after the fact and have the iframe behave as a sandboxed iframe.
Related
there have been so many discussions in regard to access iframe with javascript. however, I can't find anything that related to an iframe without 'src' attribute.
basically, I have an iframe that doesn't have any src/link, it will be created by react and bunch of element will be inserted into this iframe on the page load.
to insert element I am using 'contentDocument!.body' which is the recommended technique.
it works fine in all browsers, except Firefox. apparently, firefox Adblock removing elements from the iframe.
so is it normal behaviour? even though iframe doesn't have an 'src' attribute and created directly in the page, shouldn't be treated as normal dom element?
I think I found the problem!
I have been creating the iframe dynamically with javascript. but look like the iframe must be rendered in the server side, and then it can be referenced and used safely to communicate with the main page
For one of my Chrome extension project, I fetched the HTML content of another webpage in an <iframe> tag of the current webpage, by populating its src attribute dynamically. Now, I want to scrape a few values from inside the <iframe> tag. But the jQuery always shows this <iframe> tag as empty. The reason I am using is that there are a few JavaScript files inside the fetched page that I want to get executed before I start scraping. I also tried to set wait timers, but jQuery always shows <iframe> tag to be empty (though the src attribute is set).
Upon investigation, I found that the <iframe> has a strange #document value inside it, followed by the normal HTML tags. I wonder if this is the reason why the jQuery is unable to recurse through a DOM hierarchy inside the <iframe> tag.
See below screenshot of the "inspect" view of the desired <iframe> tag.
Also, the main webpage on which the <iframe> tag exists is on the same website as the newly fetch page url (albeit a different subdomain). And I'm not getting any access permission warnings in Chrome, so I do not suspect this to be a cross-domain issue.
Edit:
Even after 10 seconds wait:
console.log($("#insertHere").text());
returns empty. And,
console.log($("#insertHere").parent().html());
returns: <iframe id="insertHere" src="/courses/intro..." style="width:0;height:0;border:0; border:none;"></iframe>
You can grab iframe content with such code :
$('#insertHere').contents().find("html").html();
$('#insertHere').contents().find("#MathJax_Message").text();
If the iframe is on another domain (seems to not be in your case), cross-site-scripting (XSS) protection of your browser will block it.
The #document is a page document object for the iFrame DOM.
Try accessing the document of the iframe, e.g.
var frame = document.getElementById('#hidden-frame');
console.log(frame.document.body);
You could also try using a Content Script and allowing it in all pages with <all_urls>, which should be loaded with the iframe content, and use it to send the content to background script using messaging.
I didn't think this was possible, however, i found this quote:
"It is strongly discouraged to use both allow-scripts and allow-same-origin at the same time, as that allows the embedded document to programmatically remove the sandbox attribute."
My iframe needs to have a sandbox, but only when I am browsing in certain URLs where the embedded browsing context tries to navigate (load) content to the top-level browsing context (Jump out of frame...)
On other pages the sandbox needs to be removed entirely, as it wont allow me to browse away from a site with a different origin...
The frame attempting navigation is sandboxed, and is therefore disallowed from navigating its ancestors.
Programatically changing the sandbox with :
document.getElementById("frame").sandbox = "";
...doesnt work either as this still places restrictions... Therefore, i need to somehow remove the attribute entirely, how would i go about doing this?
These flags only take effect when the nested browsing context of the
iframe is navigated. Removing them, or removing the entire sandbox
attribute, has no effect on an already-loaded page.
More info - Here
You can remove the sandbox attribute from the element using iframe.removeAttribute("sandbox") this will make the iframe non-sandboxed for the next content you load into it, not the currently loaded one.
I have a page named somepage.html and the page otherpage.html as iframe in somepage.html
the source of somepage.html is
<body><iframe src="otherpage.html name="frame"></body>
The source of otherpage.html is
<body onload="somefunction()" onunload="otherfunction" >the other content here</body>
I want to disable the onload function without touching the code of otherpage.html(iframe). I want to disable it on somepage.html
Thank you in advance
In IE you can use the security="restricted" attribute. It doesn't do what you want (disable javascript altogether) but should force the IFRAME to run in a differnent zone and prevent it from accessing your page.
The HTML 5 sandbox attribute, when implemented, may also be close to what you are looking for. In particular allow-scripts. Now you just need it to be implemented in a majority of user's browsers ;)
The scene: I'm writing an embeddable widget. It takes the form of a <script> tag, which builds an iframe containing everything it needs to display. The iframe has no src, and the script writes to it with theIframe.contentWindow.document.write(). This keeps the widget contained, and keeps element ids and script from conflicting with the page on which the widget is embedded.
The trick: The widget has to be able to change its size. To do this, it sets its containing iframe's style.height. This requires access to the outer page's DOM. In Firefox and IE, this is allowed, because the iframe's document and the outer document are considered to share an origin.
The twist: In Safari, however, the two documents are considered not to share an origin. The inner document is considered to be at about:blank, while the outer document is clearly using a different protocol and "domain" (if blank can be considered the domain).
The question: How can I build an iframe programmatically whose document Safari/WebKit will consider to have the same origin as the document of the window creating it?
Edit: After further experimentation, I can't find a way to programmatically create an iframe whose location is not about:blank regardless of whether I change its contents.
If I create the frame with document.createElement(), give it a src which points to a real HTML resource on the same origin called "foo.html", and document.body.appendChild() it, Safari's console shows the element as expected in the DOM, but the contents of the page do not appear, and the document is listed in the sidebar as "about:blank".
If I include the HTML for the iframe directly in the page, the contents of foo.html appear, and "foo.html" appears in the sidebar.
If I insert the HTML using document.write(), I get the same result as with document.body.appendChild().
Both programmatic versions work in Firefox.
The best suggestion I could give is to have the iframe set to a blank page on the same server (ie blank.html) and then edit the content. A pain in the rear, I know but it's a workaround.
You could also try
iframe.contentDocument.open("replace");
iframe.contentDocument.write("<b>This is some content</b>");
iframe.contentDocument.close();
However, I'm not sure if that only works in IE. Sorry I couldn't be more helpful than that.
Aha. This seems to be a bug in WebKit. When an iframe is created programmatically, its src attribute is ignored. Instead, the frame defaults to about:blank and must be directed to a URL to point elsewhere. For example:
theIframe.contentWindow.location = theIframe.src