RESOLVED FIXED 141316
ScriptController::initScript should not subject to CSP if the world it is running in is isolated world
https://bugs.webkit.org/show_bug.cgi?id=141316
Summary ScriptController::initScript should not subject to CSP if the world it is run...
Zach Li
Reported 2015-02-05 18:19:20 PST
In ScriptController:initScript, we can see whether we allow "eval" is based on the Content Security Policy of the page. Scripts running in isolated world should not subject to this.
Attachments
Patch (1.30 KB, patch)
2015-02-10 17:34 PST, Zach Li
kling: review-
Patch (9.20 KB, patch)
2015-03-18 16:39 PDT, Zach Li
no flags
Patch v2 (7.09 KB, patch)
2015-03-23 17:38 PDT, Zach Li
no flags
Zach Li
Comment 1 2015-02-10 17:34:13 PST
Andreas Kling
Comment 2 2015-02-11 13:19:06 PST
Comment on attachment 246354 [details] Patch I'd prefer if someone with good knowledge about CSP (perhaps Sam or Alexey?) could review this. Regardless, a change like this should include a layout test to prove that we're doing the right thing (and guard against future regressions.)
Alexey Proskuryakov
Comment 3 2015-02-18 14:53:18 PST
See also: bug 104520 and <rdar://problem/18860261>. This makes me reluctant about giving non-main worlds more power.
Zach Li
Comment 4 2015-03-18 16:39:21 PDT
Created attachment 248985 [details] Patch Patch.
Daniel Bates
Comment 5 2015-03-23 13:51:49 PDT
Comment on attachment 248985 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=248985&action=review > LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp.html:34 > + new Function('return true'); Is it not possible to write this function using eval()? > LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp.html:35 > + alert('LOADED in ' + (isolated ? "isolated world" : "main world")); This message is disingenuous because we did not load anything. Maybe change LOADED to "Implicitly called eval()" (or "Called eval()" if we can write this function using eval())? > LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp.html:39 > + alert('BLOCKED in ' + (isolated ? "isolated world" : "main world")); This message is not very clear what we are blocking. We should elaborate that we blocked eval(). > LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp.html:61 > + testRunner.evaluateScriptInIsolatedWorld(1, String(function setImgSrc(isolated) { > + var img = document.createElement('img'); > + document.body.appendChild(img); > + img.onload = function () { > + alert('LOADED in ' + (isolated ? "isolated world" : "main world")); > + window.postMessage("next", "*"); > + }; > + img.onerror = function () { > + alert('BLOCKED in ' + (isolated ? "isolated world" : "main world")); > + window.postMessage("next", "*"); > + }; > + img.src = "../resources/abe.png"; > + }) + "\nsetImgSrc(true);"); Can we use String(setImgSrc) to get a string representation of the source code of function setImgSrc? > LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp.html:76 > + testRunner.evaluateScriptInIsolatedWorld(1, String(function createNewFunction(isolated) { > + try { > + new Function('return true'); > + alert('LOADED in ' + (isolated ? 'isolated world' : 'main world')); > + window.postMessage('next', '*'); > + } catch (error) { > + alert('BLOCKED in ' + (isolated ? 'isolated world' : 'main world')); > + window.postMessage('next', '*'); > + } > + }) + "\ncreateNewFunction(true);"); Similarly, can we use String(createNewFunction)? > Source/WebCore/bindings/js/ScriptController.cpp:258 > + bool shouldBypassMainWorldContentSecurityPolicy = !world.isNormal(); > if (m_frame.document()) > - windowShell->window()->setEvalEnabled(m_frame.document()->contentSecurityPolicy()->allowEval(0, ContentSecurityPolicy::SuppressReport), m_frame.document()->contentSecurityPolicy()->evalDisabledErrorMessage()); > + windowShell->window()->setEvalEnabled(shouldBypassMainWorldContentSecurityPolicy ? shouldBypassMainWorldContentSecurityPolicy : m_frame.document()->contentSecurityPolicy()->allowEval(0, ContentSecurityPolicy::SuppressReport), m_frame.document()->contentSecurityPolicy()->evalDisabledErrorMessage()); It's unnecessary to compute ContentSecurityPolicy::evalDisabledErrorMessage() when shouldBypassMainWorldContentSecurityPolicy evaluates to true. I would have written this as: if (m_frame.document()) { bool shouldBypassMainWorldContentSecurityPolicy = !world.isNormal(); if (shouldBypassMainWorldContentSecurityPolicy) windowShell->window()->setEvalEnabled(true); else windowShell->window()->setEvalEnabled(m_frame.document()->contentSecurityPolicy()->allowEval(0, ContentSecurityPolicy::SuppressReport), m_frame.document()->contentSecurityPolicy()->evalDisabledErrorMessage()); } Notice that I also moved the initialization of shouldBypassMainWorldContentSecurityPolicy such that we only perform it when m_frame.document() is non-null, which is when we actually need to make use of its value.
Zach Li
Comment 6 2015-03-23 17:38:18 PDT
Created attachment 249304 [details] Patch v2
Geoffrey Garen
Comment 7 2015-03-24 17:10:29 PDT
What is our answer to the security concern here?
Geoffrey Garen
Comment 8 2015-03-24 17:17:45 PDT
Comment on attachment 249304 [details] Patch v2 I don't think this patch is any worse than the existing behavior in CachedResourceLoader::canRequest. That said, it looks like our approach to CSP is pretty badly broken in the face of extensions and browser JavaScript.
WebKit Commit Bot
Comment 9 2015-03-24 18:29:10 PDT
Comment on attachment 249304 [details] Patch v2 Clearing flags on attachment: 249304 Committed r181925: <http://trac.webkit.org/changeset/181925>
WebKit Commit Bot
Comment 10 2015-03-24 18:29:18 PDT
All reviewed patches have been landed. Closing bug.
Daniel Bates
Comment 11 2015-07-27 19:07:47 PDT
Note You need to log in before you can comment on or make changes to this bug.