I have an application (http://localhost/MyApp
), where some of the parts are rendered through IFRAMES. These iframed parts has no business with the rest of the application's DOM, so I applied the sandbox
attribute.
The IFRAME is declared like this:
<iframe src="/MyApp/en/html/action?id=1" sandbox="allow-forms allow-scripts" seamless="seamless"></iframe>
The iframed page has a button that makes a AJAX call to the same web application, but then rather than a HTTP GET
, the browser issues a HTTP OPTIONS
that appears as Cancelled
, and an error happens:
XMLHttpRequest cannot load http://localhost/MyApp/en/data/action?id=1. Cannot make any requests from null.
Ajax State 0 Error: HTTP 0
If I add the allow-same-origin
to the sandbox
attribute, it works.As far as I read here, it was not supposed to affect AJAX calls.
Why is this happening? Is considering the path /MyApp/en/html/action
as origin of the whole IFRAME and blocking the request to previous levels?
Cheers.
The reason it affects Ajax is because Ajax is governed by the Same Origin Policy rules, and when you sandbox it you're effectively telling the browser to treat the
iframe
contents as if it were from a different origin. Quoting the same article:In other words, if you omit the
allow-same-origin
in thesandbox
attribute, it will treat the sandboxed page as belonging to a different domain (in fact, it will treat as having anull
origin). Since it doesn't make sense to make Ajax requests tonull
, sandboxed pages can not make Ajax calls at all (if making them tolocalhost
were allowed they would be indistinguishable from the calls from the parent page, defeating the purpose of sandboxing).Additional info
If you try to make an Ajax call to a different domain, it will obviously fail:
However, how it will fail will depend on the sandbox attribute used. If you embed the page above in an
iframe
withallow-same-origin
it will print this to the console:...and if you embed it without
allow-same-origin
:Note that, while both reported
location.host
aslocalhost
, one considered the origin to behttp://localhost
while the other considered it to benull
(showing the same error message you experienced in your example).Reasoning
Why is it so important to block Ajax calls from sandboxed contents from the same domain? As explained in the article:
Let's make up an example: suppose Facebook decides to allow users post little HTML5 animations in their pages. It stores them in its own servers and, when displaying, sandboxes them as
allow-scripts
only (because scripts are needed for the animations to work) but leave everything else denied (in particularallow-same-origin
, since you don't want user code messing up with the parent page). What would happen if Ajax calls weren't also blocked by default?Mallory creates an "animation" that consists of:
Performing an Ajax call to Facebook, using its API (say, Open Graph); the server will happily accept the call, since for all it knows the request came from a page with
https://facebook.com
as origin.Create a URI pointing to her own server, with the returned data as query strings, and set it as the
src
of a picture in the sandboxed page.When Alice visits Mallory profile, and sees the animation, the script above runs:
The Ajax call runs in Alice's browser, while Alice is logged on; since the server does not know where the call comes from (main page or embedded page) it will do whatever it's asked to - including retrieving personal info.
When the
img
element is created with Mallory's URI, the browser will attempt to load the "image" normally, since images are exempt from the Same Origin Policy.Since the URI has Alice's private info in the query string, Mallory's server can just save it and return whatever image it wants. Now Mallory has Alice's personal info, and Alice suspects nothing.