Title: [138817] trunk
Revision
138817
Author
mk...@chromium.org
Date
2013-01-04 11:09:12 -0800 (Fri, 04 Jan 2013)

Log Message

CSP: XHR from an isolated world should bypass a page's policy.
https://bugs.webkit.org/show_bug.cgi?id=104480

Reviewed by Adam Barth.

Source/WebCore:

Connections of various types are governed by the page's Content Security
Policy 'connect-src' directive. In the special case of connections
generated from an isolated world, we'd like to bypass these restrictions
in order to allow things like extensions to enjoy their uniquely high-
privilege lifestyle. This patch does just that.

We'll lock them down to their own policy in webkit.org/b/104520, but
that's a bit far away at the moment. Soon!

Test: http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html

* Modules/websockets/WebSocket.cpp:
(WebCore::WebSocket::connect):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::canRequest):
* page/EventSource.cpp:
(WebCore::EventSource::create):
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::open):
    Check whether or not code is running in an isolated world that has
    its own Content Security Policy. If so, bypass the main world's CSP
    checks. Isolated worlds gotta be free, man.

LayoutTests:

* http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr-expected.txt: Added.
* http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html: Added.
    A new test! How wonderful!
* platform/efl/TestExpectations:
* platform/mac/TestExpectations:
* platform/qt/TestExpectations:
* platform/win/TestExpectations:
* platform/wincairo/TestExpectations:
    Skipping the new test on ports that don't support it.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (138816 => 138817)


--- trunk/LayoutTests/ChangeLog	2013-01-04 19:02:51 UTC (rev 138816)
+++ trunk/LayoutTests/ChangeLog	2013-01-04 19:09:12 UTC (rev 138817)
@@ -1,3 +1,20 @@
+2013-01-04  Mike West  <mk...@chromium.org>
+
+        CSP: XHR from an isolated world should bypass a page's policy.
+        https://bugs.webkit.org/show_bug.cgi?id=104480
+
+        Reviewed by Adam Barth.
+
+        * http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr-expected.txt: Added.
+        * http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html: Added.
+            A new test! How wonderful!
+        * platform/efl/TestExpectations:
+        * platform/mac/TestExpectations:
+        * platform/qt/TestExpectations:
+        * platform/win/TestExpectations:
+        * platform/wincairo/TestExpectations:
+            Skipping the new test on ports that don't support it.
+
 2013-01-04  Mike Lawther  <mikelawt...@chromium.org>
 
         CSS3 calc: mixed percent/absolute for border-radius

Added: trunk/LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr-expected.txt (0 => 138817)


--- trunk/LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr-expected.txt	2013-01-04 19:09:12 UTC (rev 138817)
@@ -0,0 +1,27 @@
+CONSOLE MESSAGE: Refused to connect to 'http://localhost:8000/security/isolatedWorld/resources/cross-origin-xhr.txt' because it violates the following Content Security Policy directive: "connect-src 'none'".
+
+CONSOLE MESSAGE: Refused to connect to 'http://localhost:8000/security/isolatedWorld/resources/cross-origin-xhr.txt' because it violates the following Content Security Policy directive: "connect-src 'none'".
+
+CONSOLE MESSAGE: Refused to connect to 'http://localhost:8000/security/isolatedWorld/resources/cross-origin-xhr.txt' because it violates the following Content Security Policy directive: "connect-src 'none'".
+
+CONSOLE MESSAGE: Refused to connect to 'http://localhost:8000/security/isolatedWorld/resources/cross-origin-xhr.txt' because it violates the following Content Security Policy directive: "connect-src 'none'".
+
+Tests that isolated worlds can have XHRs that the page's CSP wouldn't allow.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+XHR from main world
+PASS: XHR.open threw an exception.
+XHR from isolated world with unchanged CSP
+PASS: XHR.open threw an exception.
+XHR from isolated world with same security origin as XHR target.
+PASS: XHR.open threw an exception.
+XHR from isolated world with same security origin as XHR target, and looser CSP.
+PASS: XHR.open did not throw an exception.
+XHR from main world is not affected by the isolated world origin or CSP
+PASS: XHR.open threw an exception.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html (0 => 138817)


--- trunk/LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html	2013-01-04 19:09:12 UTC (rev 138817)
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+    <script src=""
+    <meta http-equiv="Content-Security-Policy" content="connect-src 'none'">
+<body>
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+description('Tests that isolated worlds can have XHRs that the page\'s CSP wouldn\'t allow.');
+
+jsTestIsAsync = true;
+
+var tests = [
+    function() {
+        debug('XHR from main world');
+        xhr(true);
+    },
+    function() {
+        debug('XHR from isolated world with unchanged CSP');
+        runTestInWorld(1, 'xhr', 'true');
+    },
+    function() {
+        debug('XHR from isolated world with same security origin as XHR target.');
+        testRunner.setIsolatedWorldSecurityOrigin(2, 'http://localhost:8000');
+        runTestInWorld(2, 'xhr', 'true');
+    },
+    function() {
+        debug('XHR from isolated world with same security origin as XHR target, and looser CSP.');
+        testRunner.setIsolatedWorldContentSecurityPolicy(3, 'connect-src *');
+        testRunner.setIsolatedWorldSecurityOrigin(3, 'http://localhost:8000');
+        runTestInWorld(3, 'xhr', 'false');
+    },
+    function() {
+        debug('XHR from main world is not affected by the isolated world origin or CSP');
+        xhr(true);
+    }
+];
+var currentTest = 0;
+
+// This test is meaningless without testRunner.
+if (window.testRunner) {
+    window.addEventListener(
+        'message',
+        function(event) {
+            var message = JSON.parse(event.data);
+            switch (message.type) {
+                case 'test-done':
+                    currentTest++;
+                    if (currentTest == tests.length) {
+                        testRunner.setIsolatedWorldSecurityOrigin(1, null);
+                        testRunner.setIsolatedWorldSecurityOrigin(2, null);
+                        testRunner.setIsolatedWorldSecurityOrigin(3, null);
+                        testRunner.setIsolatedWorldContentSecurityPolicy(1, '');
+                        testRunner.setIsolatedWorldContentSecurityPolicy(2, '');
+                        testRunner.setIsolatedWorldContentSecurityPolicy(3, '');
+                        finishJSTest();
+                    }
+                    else
+                        tests[currentTest]();
+                    break;
+                case 'debug':
+                    debug(message.message);
+                    break;
+                default:
+                    testFailed('Unknown message: ' + event.data);
+                    break;
+            }
+        },
+        false);
+
+    tests[0]();
+} else {
+    testFailed('Test depends on LayoutTestController and must be run by DRT');
+}
+
+function runTestInWorld(worldId, funcName, param)
+{
+    testRunner.evaluateScriptInIsolatedWorld(
+        worldId, String(eval(funcName)) + "\n" + funcName + "(" + param + ");");
+}
+
+function xhr(shouldBlock)
+{
+    function debug(message) {
+        window.postMessage(JSON.stringify({
+                'type': 'debug',
+                'message': message
+            }),
+            '*');
+    }
+
+    var xhr = new XMLHttpRequest();
+    try {
+        xhr.open('GET', 'http://localhost:8000/security/isolatedWorld/resources/cross-origin-xhr.txt', true);
+        if (shouldBlock)
+            debug('FAIL: XHR.open should have thrown an exception.');
+        else
+            debug('PASS: XHR.open did not throw an exception.');
+    } catch (e) {
+        if (shouldBlock)
+            debug('PASS: XHR.open threw an exception.');
+        else
+            debug('FAIL: XHR.open should not have thrown an exception.');
+    } finally {
+        window.postMessage(JSON.stringify({'type': 'test-done'}), '*');
+    }
+}
+
+</script>
+
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/platform/efl/TestExpectations (138816 => 138817)


--- trunk/LayoutTests/platform/efl/TestExpectations	2013-01-04 19:02:51 UTC (rev 138816)
+++ trunk/LayoutTests/platform/efl/TestExpectations	2013-01-04 19:09:12 UTC (rev 138817)
@@ -1129,6 +1129,7 @@
 
 # JSC also doesn't support setIsolatedWorldContentSecurityPolicy
 webkit.org/b/100815 http/tests/security/isolatedWorld/bypass-main-world-csp.html [ Failure ]
+webkit.org/b/100815 http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html [ Failure ]
 
 #__worldID is undefined in isolated world
 Bug(EFL) http/tests/security/isolatedWorld/didClearWindowObject.html

Modified: trunk/LayoutTests/platform/mac/TestExpectations (138816 => 138817)


--- trunk/LayoutTests/platform/mac/TestExpectations	2013-01-04 19:02:51 UTC (rev 138816)
+++ trunk/LayoutTests/platform/mac/TestExpectations	2013-01-04 19:09:12 UTC (rev 138817)
@@ -439,7 +439,8 @@
 http/tests/security/isolatedWorld/cross-origin-xhr.html
 
 # JSC also doesn't support setIsolatedWorldContentSecurityPolicy (webkit.org/b/100815)
-http/tests/security/isolatedWorld/bypass-main-world-csp.html
+webkit.org/b/100815 http/tests/security/isolatedWorld/bypass-main-world-csp.html [ Failure ]
+webkit.org/b/100815 http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html [ Failure ]
 
 # https://bugs.webkit.org/show_bug.cgi?id=63282 layerTreeAsText doesn't work for iframes
 compositing/rtl/rtl-iframe-absolute-overflow-scrolled.html

Modified: trunk/LayoutTests/platform/qt/TestExpectations (138816 => 138817)


--- trunk/LayoutTests/platform/qt/TestExpectations	2013-01-04 19:02:51 UTC (rev 138816)
+++ trunk/LayoutTests/platform/qt/TestExpectations	2013-01-04 19:09:12 UTC (rev 138817)
@@ -205,7 +205,8 @@
 http/tests/security/isolatedWorld/cross-origin-xhr.html
 
 # JSC also doesn't support setIsolatedWorldContentSecurityPolicy (webkit.org/b/100815)
-http/tests/security/isolatedWorld/bypass-main-world-csp.html
+webkit.org/b/100815 http/tests/security/isolatedWorld/bypass-main-world-csp.html [ Failure ]
+webkit.org/b/100815 http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html [ Failure ]
 
 # This test is for clients that choose to make the missing plugin indicator a button
 plugins/clicking-missing-plugin-fires-delegate.html

Modified: trunk/LayoutTests/platform/win/TestExpectations (138816 => 138817)


--- trunk/LayoutTests/platform/win/TestExpectations	2013-01-04 19:02:51 UTC (rev 138816)
+++ trunk/LayoutTests/platform/win/TestExpectations	2013-01-04 19:09:12 UTC (rev 138817)
@@ -1493,7 +1493,8 @@
 http/tests/security/isolatedWorld/cross-origin-xhr.html
 
 # JSC also doesn't support setIsolatedWorldContentSecurityPolicy (webkit.org/b/100815)
-http/tests/security/isolatedWorld/bypass-main-world-csp.html
+webkit.org/b/100815 http/tests/security/isolatedWorld/bypass-main-world-csp.html [ Failure ]
+webkit.org/b/100815 http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html [ Failure ]
 
 # ENABLE(WEBGL) is disabled
 compositing/backface-visibility/backface-visibility-webgl.html

Modified: trunk/LayoutTests/platform/wincairo/TestExpectations (138816 => 138817)


--- trunk/LayoutTests/platform/wincairo/TestExpectations	2013-01-04 19:02:51 UTC (rev 138816)
+++ trunk/LayoutTests/platform/wincairo/TestExpectations	2013-01-04 19:09:12 UTC (rev 138817)
@@ -2023,7 +2023,8 @@
 http/tests/security/isolatedWorld/cross-origin-xhr.html
 
 # JSC also doesn't support setIsolatedWorldContentSecurityPolicy (webkit.org/b/100815)
-http/tests/security/isolatedWorld/bypass-main-world-csp.html
+webkit.org/b/100815 http/tests/security/isolatedWorld/bypass-main-world-csp.html [ Failure ]
+webkit.org/b/100815 http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html [ Failure ]
 
 # ENABLE(WEBGL) is disabled
 compositing/backface-visibility/backface-visibility-webgl.html

Modified: trunk/Source/WebCore/ChangeLog (138816 => 138817)


--- trunk/Source/WebCore/ChangeLog	2013-01-04 19:02:51 UTC (rev 138816)
+++ trunk/Source/WebCore/ChangeLog	2013-01-04 19:09:12 UTC (rev 138817)
@@ -1,3 +1,33 @@
+2013-01-04  Mike West  <mk...@chromium.org>
+
+        CSP: XHR from an isolated world should bypass a page's policy.
+        https://bugs.webkit.org/show_bug.cgi?id=104480
+
+        Reviewed by Adam Barth.
+
+        Connections of various types are governed by the page's Content Security
+        Policy 'connect-src' directive. In the special case of connections
+        generated from an isolated world, we'd like to bypass these restrictions
+        in order to allow things like extensions to enjoy their uniquely high-
+        privilege lifestyle. This patch does just that.
+
+        We'll lock them down to their own policy in webkit.org/b/104520, but
+        that's a bit far away at the moment. Soon!
+
+        Test: http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html
+
+        * Modules/websockets/WebSocket.cpp:
+        (WebCore::WebSocket::connect):
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::CachedResourceLoader::canRequest):
+        * page/EventSource.cpp:
+        (WebCore::EventSource::create):
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::open):
+            Check whether or not code is running in an isolated world that has
+            its own Content Security Policy. If so, bypass the main world's CSP
+            checks. Isolated worlds gotta be free, man.
+
 2013-01-04  Mike Lawther  <mikelawt...@chromium.org>
 
         CSS3 calc: mixed percent/absolute for border-radius

Modified: trunk/Source/WebCore/Modules/websockets/WebSocket.cpp (138816 => 138817)


--- trunk/Source/WebCore/Modules/websockets/WebSocket.cpp	2013-01-04 19:02:51 UTC (rev 138816)
+++ trunk/Source/WebCore/Modules/websockets/WebSocket.cpp	2013-01-04 19:09:12 UTC (rev 138817)
@@ -39,11 +39,13 @@
 #include "CloseEvent.h"
 #include "ContentSecurityPolicy.h"
 #include "DOMWindow.h"
+#include "Document.h"
 #include "Event.h"
 #include "EventException.h"
 #include "EventListener.h"
 #include "EventNames.h"
 #include "ExceptionCode.h"
+#include "Frame.h"
 #include "Logging.h"
 #include "MessageEvent.h"
 #include "ScriptCallStack.h"
@@ -238,7 +240,13 @@
         return;
     }
 
-    if (!scriptExecutionContext()->contentSecurityPolicy()->allowConnectToSource(m_url)) {
+    // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved.
+    bool shouldBypassMainWorldContentSecurityPolicy = false;
+    if (scriptExecutionContext()->isDocument()) {
+        Document* document = static_cast<Document*>(scriptExecutionContext());
+        shouldBypassMainWorldContentSecurityPolicy = document->frame()->script()->shouldBypassMainWorldContentSecurityPolicy();
+    }
+    if (!shouldBypassMainWorldContentSecurityPolicy && !scriptExecutionContext()->contentSecurityPolicy()->allowConnectToSource(m_url)) {
         m_state = CLOSED;
 
         // FIXME: Should this be throwing an exception?

Modified: trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp (138816 => 138817)


--- trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2013-01-04 19:02:51 UTC (rev 138816)
+++ trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2013-01-04 19:09:12 UTC (rev 138817)
@@ -310,6 +310,7 @@
         return 0;
     }
 
+    // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved.
     bool shouldBypassMainWorldContentSecurityPolicy = (frame() && frame()->script()->shouldBypassMainWorldContentSecurityPolicy());
 
     // Some types of resources can be loaded only from the same origin.  Other

Modified: trunk/Source/WebCore/page/EventSource.cpp (138816 => 138817)


--- trunk/Source/WebCore/page/EventSource.cpp	2013-01-04 19:02:51 UTC (rev 138816)
+++ trunk/Source/WebCore/page/EventSource.cpp	2013-01-04 19:09:12 UTC (rev 138817)
@@ -36,9 +36,11 @@
 #include "ContentSecurityPolicy.h"
 #include "DOMWindow.h"
 #include "Dictionary.h"
+#include "Document.h"
 #include "Event.h"
 #include "EventException.h"
 #include "ExceptionCode.h"
+#include "Frame.h"
 #include "MemoryCache.h"
 #include "MessageEvent.h"
 #include "ResourceError.h"
@@ -83,7 +85,13 @@
         return 0;
     }
 
-    if (!context->contentSecurityPolicy()->allowConnectToSource(fullURL)) {
+    // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved.
+    bool shouldBypassMainWorldContentSecurityPolicy = false;
+    if (context->isDocument()) {
+        Document* document = static_cast<Document*>(context);
+        shouldBypassMainWorldContentSecurityPolicy = document->frame()->script()->shouldBypassMainWorldContentSecurityPolicy();
+    }
+    if (!shouldBypassMainWorldContentSecurityPolicy && !context->contentSecurityPolicy()->allowConnectToSource(fullURL)) {
         // FIXME: Should this be throwing an exception?
         ec = SECURITY_ERR;
         return 0;

Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (138816 => 138817)


--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2013-01-04 19:02:51 UTC (rev 138816)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2013-01-04 19:09:12 UTC (rev 138817)
@@ -493,7 +493,13 @@
         return;
     }
 
-    if (!scriptExecutionContext()->contentSecurityPolicy()->allowConnectToSource(url)) {
+    // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved.
+    bool shouldBypassMainWorldContentSecurityPolicy = false;
+    if (scriptExecutionContext()->isDocument()) {
+        Document* document = static_cast<Document*>(scriptExecutionContext());
+        shouldBypassMainWorldContentSecurityPolicy = document->frame()->script()->shouldBypassMainWorldContentSecurityPolicy();
+    }
+    if (!shouldBypassMainWorldContentSecurityPolicy && !scriptExecutionContext()->contentSecurityPolicy()->allowConnectToSource(url)) {
         // FIXME: Should this be throwing an exception?
         ec = SECURITY_ERR;
         return;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to