Extension content script works on page with Content-Security-Policy: sandbox unless uses setTimeout
Reported by
peter.m....@gmail.com,
Feb 12 2018
|
|||||||
Issue descriptionChrome Version: 64.0.3282.140 OS Version: OS X 10.13.2 URLs: https://mrcoles.com/csp-sandbox (test page with response header "Content-Security-Policy: sandbox ;" What steps will reproduce the problem? 1. Clone this repo: https://github.com/mrcoles/test-chrome-extension-sandbox 2. Add as an unpacked extension 3. Go to this page https://mrcoles.com/csp-sandbox (which has the sandbox response header) 4. Click on the popup button to trigger the extension. What is the expected result? Should output the messages: > 1. chrome.tabs.executeScript(..., page.js) > 2. chrome.tabs.executeScript callback! > 3. chrome.tabs.sendMessage(..., test) > 4. chrome.tabs.sendMessage callback! What happens instead of that? It outputs the messages: > 1. chrome.tabs.executeScript(..., page.js) > 2. chrome.tabs.executeScript callback! > 3. chrome.tabs.sendMessage(..., test) Please provide any additional information below. Attach a screenshot if possible. The content script "page.js" listens for a message and then calls the callback it is sent. When it’s wrapped in a `window.setTimeout(...)` and it is run on a page with "Content-Security-Policy: sandbox ;" (see linked URL above) the callback fails to call and there is *no* error, not even a `chrome.runtime.lastError` in "popup.js". If I comment out the setTimeout lines and call the callback synchronously inline, then it works fine. Also, if I keep the setTimeout, but run it on a page without that response header (like https://google.com), then it works fine and displays the 4 messages. UserAgentString: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36
,
Feb 13 2018
,
Feb 13 2018
Able to reproduce this issue on Mac 10.12.6, Win-10 and Ubuntu 14.04 using chrome reported version #64.0.3282.140 and latest canary #66.0.3345.0. This is a non-regression issue as it is observed from M60 old builds. Hence, marking it as untriaged to get more inputs from dev team. Thanks...!!
,
Feb 16 2018
@peter.m.coles, is this CSP specific? i.e. does this work without the CSP? Assigning to Devlin for sendMessage.
,
Mar 15 2018
On pages without the CSP setting, it works as expected, e.g., try on https://mrcoles.com/ instead of https://mrcoles.com/csp-sandbox
,
Mar 16 2018
Repo linked seems like it might be wrong - it looks like that one doesn't do any script injection and just has a popup?
,
Mar 26 2018
Sorry! I fixed the repo (I mistakenly overwrite it with another bug report). Original URL works again: https://github.com/mrcoles/test-chrome-extension-sandbox
,
Apr 20 2018
Sorry for the lengthy delay here!
I had a chance to investigate this, and think I know what's happening. Extensions are allowed to bypass the CSP of the page in order to inject scripts on it (which is very important). However, it looks like once we use setTimeout(), we lose the knowledge that the script running came from an extension.
In extreme cases, we can't always make the guarantee that things like this will work (because chrome doesn't have perfect taint tracking in blink, and we won't always be able to know what the appropriate execution context is). It's also, for now, a pretty deliberate non-goal to change that, because it's hard, and doing it performantly is harder.
However, this case seems like it should be easy, and could be pretty useful. In particular, we should still be executing in the same isolated world associated with the script, and it seems like having a "if (script from isolated world for extension) { bypass csp }" type logic should be doable.
jbroman@, mkwst@, any thoughts? (Both on the feasibility of such an approach and whether there's any reason we wouldn't want to do it.)
,
Apr 20 2018
Keying off the current ScriptState sounds reasonable to me.
,
Apr 24 2018
You meant to insert "if (content script) { bypass csp }" into ScheduledAction or somewhere appropriate?
I don't want to insert such code here and there randomly, but inserting such code into a (few?) specific point(s) is pretty reasonable, I think. We need to be careful, though.
,
Apr 24 2018
I don't work in blink enough to know the exact places such a check would go, and will gladly defer to blink experts there. :) But it does seem that, since we a) know which world is executing and b) exempt that world from CSP when first executing, we should be able to carry that CSP-exemption for asynchronous execution (i.e., use the world to determine whether to bypass CSP). Is there anything in particular that's worrisome, and we should make sure to be extra cautious of?
,
Apr 26 2018
> Is there anything in particular that's worrisome, and we should make sure to be extra cautious of? No, nothing. Please go ahead.
,
Apr 27 2018
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/5a5267ab58dd0310fc2b427db30de60c0eea4457 commit 5a5267ab58dd0310fc2b427db30de60c0eea4457 Author: Devlin Cronin <rdevlin.cronin@chromium.org> Date: Fri Apr 27 20:16:38 2018 [Blink + Extensions] Allow async execution in isolated worlds to bypass sandbox Isolated worlds (like extensions) are designed to be able to bypass a page's specified CSP. However, when executing an asynchronous scheduled action (such as one initiated through setTimeout()), the actions were not allowed to execute. This is because ScheduledAction::Execute() checked Document::CanExecuteScripts(), which checked if the document was sandboxed and didn't check if it should bypass the CSP. Fix this by having the document check if it should bypass the CSP, and, if it should, allow the script execution. Add unittests for Document::CanExecuteScripts() as well as an end-to-end test for an extension with a content script and setTimeout(). Bug: 811528 Change-Id: I7f6497784845a7d05d60048c84b24db9b903eae9 Reviewed-on: https://chromium-review.googlesource.com/1030952 Commit-Queue: Devlin <rdevlin.cronin@chromium.org> Reviewed-by: Jeremy Roman <jbroman@chromium.org> Reviewed-by: Kentaro Hara <haraken@chromium.org> Reviewed-by: Kouhei Ueno <kouhei@chromium.org> Cr-Commit-Position: refs/heads/master@{#554477} [modify] https://crrev.com/5a5267ab58dd0310fc2b427db30de60c0eea4457/chrome/browser/extensions/content_script_apitest.cc [add] https://crrev.com/5a5267ab58dd0310fc2b427db30de60c0eea4457/chrome/test/data/extensions/page_with_sandbox_csp.html [add] https://crrev.com/5a5267ab58dd0310fc2b427db30de60c0eea4457/chrome/test/data/extensions/page_with_sandbox_csp.html.mock-http-headers [modify] https://crrev.com/5a5267ab58dd0310fc2b427db30de60c0eea4457/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc [modify] https://crrev.com/5a5267ab58dd0310fc2b427db30de60c0eea4457/third_party/blink/renderer/core/dom/document.cc [modify] https://crrev.com/5a5267ab58dd0310fc2b427db30de60c0eea4457/third_party/blink/renderer/core/dom/document_test.cc
,
Apr 27 2018
I believe this should be fixed with #13. peter.m.coles@, feel free to test it out. Thanks very much for reporting the issue! I wouldn't be surprised if there are some other cases like this, so if you find any, let us know. :) |
|||||||
►
Sign in to add a comment |
|||||||
Comment 1 by manoranj...@chromium.org
, Feb 13 2018