JavaScript errors (localstorage, cookie) loading sandboxed iframe within Chrome Extension

11,131

Solution 1

Using allow-same-origin is fine. It does not give the content access to the Chrome extension context. It does not grant anything beyond letting the iframe retain its original origin.

You have become concerned because of the name used for this permission. In my opinion, the name of this token is inappropriate. The name allow-same-origin implies that it is giving permissions that join it with the permissions available to some other origin (those of the page in which the iframe is embedded being the most strongly implied). This is not the case. The token would have been more appropriately called allow-keep-original-origin, or something similar.

What the allow-same-origin token does is permit the page inside the iframe to retain the origin which it originally has as a result of being loaded from the URL it came from. That means that an iframe like <iframe src="http://example.com/" sandbox="allow-same-origin allow-scripts"></iframe> is permitted to run scripts and behave as if it's origin is http://example.com, nothing more than that. It does not expand that origin to that of the containing page. If the allow-same-origin token was not present, then the iframe would behave as if its origin was something like fooscheme://someTotallyUniqueOriginThatWillNeverMatchAnythingElse027365012536.yeahWeReallyMeanItWillNeverMatch (i.e. an origin that is guaranteed to never match anything else, even itself).

So, despite the name of the allow-same-origin token, it does not grant any additional special capabilities which the iframe would not otherwise have, except that it gets to retain its original origin.

Using the allow-same-origin token permits the code in the iframe to use things like cookies, DOM storage (e.g. localStorage), IndexedDB, etc. like it normally would when loaded from its original origin. Including the allow-same-origin token will be necessary for many web pages to have something close to normal operation.

I found MDN's statement on allow-same-origin:

Allows the content to be treated as being from its normal origin. If this keyword is not used, the embedded content is treated as being from a unique origin.

to be somewhat helpful in understanding this. The blog post "Play safely in sandboxed IFrames" helped a bit. The statement in the W3c HTML 5.2 specification was also helpful [emphasis mine]:

The allow-same-origin keyword is intended for two cases.

First, it can be used to allow content from the same site to be sandboxed to disable scripting, while still allowing access to the DOM of the sandboxed content.

Second, it can be used to embed content from a third-party site, sandboxed to prevent that site from opening pop-up windows, etc, without preventing the embedded page from communicating back to its originating site, using the database APIs to store data, etc.

And the additional information from the W3C HTML 5.2 specification (the sandboxed origin browsing context flag will be set unless the allow-same-origin token is present):

The sandboxed origin browsing context flag

MDN's page on Same-origin policy was also of interest.

Solution 2

To fix the issue to to Settings > Privacy > Content Settings change the cookies settings to Allow local data to be set

enter image description here

Share:
11,131
fstr
Author by

fstr

Updated on June 18, 2022

Comments

  • fstr
    fstr almost 2 years

    I'm writing a Chrome Extension that shows a preview of a website of a user's choosing in a sandboxed iframe. I'm finding that a lot of pages do not render properly in the iframe because they get JavaScript errors such which breaks scripts that are important to rendering the page (like hiding a loading dialog):

    "Uncaught DOMException: Failed to read the 'localStorage' property from 'Window':
    The document is sandboxed and lacks the 'allow-same-origin' flag."
    
    "Uncaught DOMException: Failed to read the 'cookie' property from 'Document':
    The document is sandboxed and lacks the 'allow-same-origin' flag."
    

    How can I safely sidestep these errors so that most pages will render as intended? They don't need to actually be able to save data to local storage or cookies, just render correctly. I've confirmed the same error happens if you put a sandboxed iframe on a regular website so it's not a Chrome Extension issue but I might be able to side step it because it's within a Chrome Extension.

    Some notes:

    • My understanding is enabling the 'allow-same-origin' flag would be a huge security risk as it would give the iframe access to the context of the Chrome extension so I don't want to do that. Enabling this flag does fix the issue though. (Edit: I think this might actually be safe now. Is this true given my context?)

    • In Chrome settings you can block localstorage and cookies which can cause similar errors elsewhere. These settings have no impact here.

    • I tried loading my target page with an iframe inside another iframe inside my Chrome Extension page and got the same errors.

    • Is it possible to inject JavaScript into the iframe that would implement dummy versions of 'localStorage' and 'cookie'? I looked into content scripts but couldn't find a way to alter these global objects before the page's scripts ran. Is it possible?

    My manifest file is like this:

        {
          "name": "test",
          "version": "0.0.1",
          "manifest_version": 2,
          "description": "",
          "icons": {
            "128": "assets/app-icon/app-icon-128x128.png"
          },
          "default_locale": "en",
          "background": {
            "scripts": [
              "scripts/background.js"
            ]
          },
          "permissions": [
            "clipboardWrite",
            "tabs",
            "storage",
            "webRequest",
            "webRequestBlocking",
            "unlimitedStorage",
            "<all_urls>"
          ],
          "browser_action": {
            "default_icon": {
              "128": "assets/app-icon/app-icon-128x128.png"
            }
          },
          "content_security_policy": "script-src 'self'; object-src 'self'"
        }
    

    My background.js file is this:

      chrome.browserAction.onClicked.addListener(function(tab) {
        var url = chrome.extension.getURL('app.html');
        chrome.tabs.create({url: url});
      });
    

    My app.html file is this:

       <html><body>
       <iframe src="https://codepen.io/TrentWalton/pen/eyaDr" sandbox="allow-scripts"></iframe>
        </body></html>
    

    The bottom part of the codepen URL will render a page in a regular tab but in the iframe it'll be blank because of the errors mentioned at the start of the post.

  • fstr
    fstr over 7 years
    Thanks but these settings have no impact on the iframe on my Chrome Extension page. You're right that they will cause/remove the error mentioned if it's an iframe on a normal page though.
  • fstr
    fstr over 7 years
    Thanks for that! It's a good point about the naming of the permission. Misleading names for things like this can lead to mistakes and security issues. In this case I nearly implemented a complex workaround when one wasn't needed.
  • whitneyland
    whitneyland over 6 years
    You say the name implies "it is giving permissions that [are] available to some other origin". But isn't that exactly what's it's doing? Forget for a moment the situation with a Chrome extension which is a browser specific case. In the general cross browser case, it seems to give all kinds of potentially dangerous permissions, like reading parent security cookies, etc.
  • Makyen
    Makyen over 6 years
    @Lee: No, that's not what it's doing. It's allowing the content to retain it's own origin, not take on the origin of the containing page. Please demonstrate that allow-same-origin allows reading cookies from an origin other than the iframe's own. It's not my experience that this option permits the iframe to do so. It allows the iframe to read cookies from it's own origin, not those of the including page (unless that's already it's own origin also). allow-same-origin allows it to retain it's own origin, not have the origin of the containing page.
  • whitneyland
    whitneyland over 6 years
    @Makyen It's sort of both. Yes, it's only allowing the content to use it's own origin. Yes, since the parent may be the same origin, it can read the parent's cookies. This still has the same (big) security implications. There are major sites that depend on this security, for example custom visual components in Microsoft's Power BI service. So in effect, developers have to be very careful using this flag as part of their architecture.
  • Makyen
    Makyen over 6 years
    @Lee Yes, that's a very important use. However, the option doesn't specifically allow the iframe to have the "same origin" as the parent. It allows the iframe to retain it's actual origin. Yes, an important use is to prevent frames which are served from the same origin as the parent frame from having access to that origin. But, that's a specific use case. While it's an important, and relatively common, use, the name allow-same-origin only describes what this does in that one use case, which is confusing for other use cases, as the name implies it's granting the script the "same origin".
  • Makyen
    Makyen over 6 years
    @Lee Further, the name fails to suggest how the permission affects content which is being served from other origins. Overall, what the permission is granting is the ability for the script to use it's source origin, regardless of that origin being the same as the parent, or not. In the case where the parent document and iframe are from the same source, then that's the "same origin", but the name only fits for that case. Thus, IMO, something like allow-keep-original-origin would more accurately describe exactly what the permission is actually doing.