1

I am currently working on a Chrome extension which has a script that needs to access global properties of the page. To do so, I came up with an approach very similar to Method 1 in this Stack Overflow answer, the only difference being that instead of inserting a new script element directly in the document, the extension creates an ìframe with a src attribute pointing to a HTML document that already contains such a script tag. This approach is convenient in my use case as this newly created iframe and HTML document are also used for other purposes, but this is not relevant to the minimal reproducible example showcased here.

Here's the code responsible for creating the iframe, executed via a content script content.js:

const iframe = document.createElement("iframe");
iframe.setAttribute("src", chrome.runtime.getURL("inject.html"));
document.body.insertBefore(iframe, document.body.firstChild);

Here is a simplified version of inject.html:

<!DOCTYPE html>
<html>
<body>
  <script src="inject.js"></script>
</body>
</html>

Here is inject.js (which in reality contains code accessing the global properties of the page):

console.log("Loaded!");

Finally, manifest.json sets both inject.js and inject.html as web accessible resources and injects content.js in all pages:

{
    "name": "Example",
    "version": "0.0.1",
    "author": "Pyves",
    "content_scripts": [
        {
            "all_frames": true,
            "matches": [
                "<all_urls>"
            ],
            "js": [
                "content.js"
            ]
        }
    ],
    "web_accessible_resources": [
        "inject.html",
        "inject.js"
    ],
    "manifest_version": 2
}

The extension is in particular targeting GitHub raw pages (for instance https://raw.githubusercontent.com/PyvesB/JavAssembly/master/README.md), which happen to have a sandbox Content Security Policy. So far this setup has been working like a charm, however since updating my Chromium-based browsers from version 63 to 64 earlier this month, the extension is no longer fully functional. inject.js is blocked, with the following error message in the browser's console:

Blocked script execution in 'chrome-extension://xxxx/inject.html' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.

Am I missing something here? How can I once again inject extension scripts in sandboxed frames in Chromium 64+?

Pyves
  • 6,333
  • 7
  • 41
  • 59
  • 1
    Looks like a bug to me so I've reported it in https://crbug.com/816121 – wOxxOm Feb 24 '18 at 20:21
  • @wOxxOm thanks, I've starred the bug as well! There seem to be quite a lot of opened reports related to extensions and CSP, I do hope that this one gets tackled or that someone can suggest a workaround in the meantime! – Pyves Feb 25 '18 at 10:26
  • An obvious, but somewhat complicated, workaround would be to modify DOM of the page itself instead of using an iframe. You can also use webRequest API to overwrite the CSP header. – wOxxOm Feb 25 '18 at 10:28
  • @wOxxOm By modifying the DOM of the page itself, do you mean inserting the script tags directly for instance? I have attempted that at some point as well, but it was also being blocked because of the sandbox CSP. You're right, overwriting the CPS headers would probably work, but it doesn't seem like the "right" way to solve the problem. – Pyves Feb 25 '18 at 11:18
  • Well, I don't know what your iframe does, but if it shows a UI of some kind, you can do it in the page itself with more hassle to isolate the styles. There's no need to insert script elements unless you need to run something in the page context. – wOxxOm Feb 25 '18 at 11:21

0 Answers0