Changeset 199221 in webkit
- Timestamp:
- Apr 8, 2016 12:17:50 AM (8 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r199216 r199221 1 2016-04-08 John Wilander <wilander@apple.com> 2 3 CSP: Block XHR when calling XMLHttpRequest.send() and throw network error. 4 https://bugs.webkit.org/show_bug.cgi?id=153598 5 <rdar://problem/24391483> 6 7 Reviewed by Darin Adler. 8 9 * fast/workers/resources/worker-inherits-csp-blocks-xhr.js: 10 (catch): 11 * fast/workers/worker-inherits-csp-blocks-xhr-expected.txt: 12 Changed expected error from DOMException.SECURITY_ERR to DOMException.NETWORK_ERR. 13 * http/tests/security/contentSecurityPolicy/connect-src-xmlhttprequest-blocked-expected.txt: 14 * http/tests/security/contentSecurityPolicy/connect-src-xmlhttprequest-blocked.html: 15 Now tests that XMLHttpRequest.send() is blocked if the URL voilates the connect-src directive in CSP. 16 * http/tests/security/contentSecurityPolicy/resources/worker.php: 17 Added two additional calls to XMLHttpRequest.send() and switched to receiving an error event to make 18 existing tests work with code changes. 19 * http/tests/security/contentSecurityPolicy/source-list-parsing-malformed-meta.html: 20 Added an additional call to XMLHttpRequest.send() and switched to receiving an error event to make 21 existing test work with code changes. 22 * http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr-expected.txt: 23 * http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html: 24 Added an additional call to XMLHttpRequest.send() and switched to receiving an error event to make 25 existing tests work with code changes. 26 Refactored test mechnism with additional parameters to cover synchronous/asynchronous as well as 27 same-origin/cross-origin in isolated worlds. 28 1 29 2016-04-07 Darin Adler <darin@apple.com> 2 30 -
trunk/LayoutTests/fast/workers/resources/worker-inherits-csp-blocks-xhr.js
r195948 r199221 8 8 exception = e; 9 9 } 10 // FIXME: We should be throwing a DOMException.NETWORK_ERR. See <https://bugs.webkit.org/show_bug.cgi?id=153598>. 11 var expectedExceptionCode = 1 8; // DOMException.SECURITY_ERR10 11 var expectedExceptionCode = 19; // DOMException.NETWORK_ERR 12 12 if (!exception) 13 13 self.postMessage("FAIL should throw " + expectedExceptionCode + ". But did not throw an exception."); -
trunk/LayoutTests/fast/workers/worker-inherits-csp-blocks-xhr-expected.txt
r198591 r199221 2 2 This tests that the Content Security Policy (CSP) of the owner document (this page) blocks a file-URL Web Worker from making an XHR request because the parent's CSP contains "connect-src 'none'" 3 3 4 PASS threw exception Error: SecurityError: DOM Exception 18.4 PASS threw exception Error: NetworkError: DOM Exception 19. -
trunk/LayoutTests/http/tests/security/contentSecurityPolicy/connect-src-xmlhttprequest-blocked-expected.txt
r198591 r199221 1 1 CONSOLE MESSAGE: Refused to connect to http://localhost:8000/xmlhttprequest/resources/get.txt because it does not appear in the connect-src directive of the Content Security Policy. 2 Pass 2 CONSOLE MESSAGE: Refused to connect to http://localhost:8000/xmlhttprequest/resources/get.txt because it does not appear in the connect-src directive of the Content Security Policy. 3 CONSOLE MESSAGE: Refused to connect to http://localhost:8000/xmlhttprequest/resources/get.txt because it does not appear in the connect-src directive of the Content Security Policy. 4 This tests that a Content Security Policy violation for an XHR is triggered when calling XMLHttpRequest.send(). 3 5 6 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". 7 8 9 PASS xhrSync.open("GET", "http://localhost:8000/xmlhttprequest/resources/get.txt", false) did not throw exception. 10 PASS xhrSync.send() threw exception Error: NetworkError: DOM Exception 19. 11 PASS xhrAsync.open("GET", "http://localhost:8000/xmlhttprequest/resources/get.txt", true) did not throw exception. 12 PASS xhrAsync.send() did not throw exception. 13 PASS xhrAsyncAbort.open("GET", "http://localhost:8000/xmlhttprequest/resources/get.txt", true) did not throw exception. 14 PASS xhrAsyncAbort.send();xhrAsyncAbort.abort(); did not throw exception. 15 PASS An error event was received for the asynchronous call. 16 PASS An error event was received for the aborted asynchronous call. 17 PASS successfullyParsed is true 18 19 TEST COMPLETE 20 -
trunk/LayoutTests/http/tests/security/contentSecurityPolicy/connect-src-xmlhttprequest-blocked.html
r133095 r199221 3 3 <head> 4 4 <meta http-equiv="Content-Security-Policy" content="connect-src http://127.0.0.1:8000"> 5 <script> 6 if (window.testRunner) 7 testRunner.dumpAsText(); 8 </script> 5 <script src="../../../resources/js-test-pre.js"></script> 9 6 </head> 10 7 <body> 11 <pre id="console"></pre>12 8 <script> 13 function log(msg) 14 { 15 document.getElementById("console").appendChild(document.createTextNode(msg + "\n")); 16 } 9 description("This tests that a Content Security Policy violation for an XHR is triggered when calling XMLHttpRequest.send()."); 17 10 18 try { 19 var xhr = new XMLHttpRequest; 20 xhr.open("GET", "http://localhost:8000/xmlhttprequest/resources/get.txt", true); 21 log("Fail"); 22 } catch(e) { 23 log("Pass"); 24 } 11 jsTestIsAsync = true; 12 13 var xhrSync = new XMLHttpRequest; 14 xhrSync.addEventListener("error", function () { 15 debug("FAIL An error event should not have been received."); 16 }); 17 18 var xhrAsync = new XMLHttpRequest; 19 xhrAsync.addEventListener("error", function () { 20 debug("PASS An error event was received for the asynchronous call."); 21 }); 22 23 var xhrAsyncAbort = new XMLHttpRequest; 24 xhrAsyncAbort.addEventListener("error", function () { 25 debug("PASS An error event was received for the aborted asynchronous call."); 26 finishJSTest(); 27 }); 28 29 shouldNotThrow('xhrSync.open("GET", "http://localhost:8000/xmlhttprequest/resources/get.txt", false)'); // Synchronous request 30 shouldThrow("xhrSync.send()", "'Error: NetworkError: DOM Exception 19'"); 31 32 shouldNotThrow('xhrAsync.open("GET", "http://localhost:8000/xmlhttprequest/resources/get.txt", true)'); // Asynchronous request 33 shouldNotThrow("xhrAsync.send()"); 34 35 shouldNotThrow('xhrAsyncAbort.open("GET", "http://localhost:8000/xmlhttprequest/resources/get.txt", true)'); // Asynchronous request 36 shouldNotThrow("xhrAsyncAbort.send();xhrAsyncAbort.abort(); "); 25 37 26 38 </script> 39 <script src="/js-test-resources/js-test-post.js"></script> 27 40 </body> 28 41 </html> -
trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/worker.php
r195367 r199221 59 59 ?> 60 60 61 try { 62 var xhr = new XMLHttpRequest; 63 xhr.open("GET", "http://127.0.0.1:8000/xmlhttprequest/resources/get.txt", true); 61 var xhr = new XMLHttpRequest; 62 xhr.addEventListener("load", function () { 64 63 postMessage("xhr allowed"); 65 } catch(e) { 64 }); 65 xhr.addEventListener("error", function () { 66 66 postMessage("xhr blocked"); 67 } 67 }); 68 xhr.open("GET", "http://127.0.0.1:8000/xmlhttprequest/resources/get.txt", true); 69 xhr.send(); 68 70 69 71 <?php … … 116 118 ?> 117 119 118 try { 119 var xhr = new XMLHttpRequest; 120 xhr.open("GET", "http://127.0.0.1:8000/xmlhttprequest/resources/get.txt", true); 120 var xhr = new XMLHttpRequest; 121 xhr.addEventListener("load", function () { 121 122 postMessage("xhr allowed"); 122 } catch(e) { 123 }); 124 xhr.addEventListener("error", function () { 123 125 postMessage("xhr blocked"); 124 } 126 }); 127 xhr.open("GET", "http://127.0.0.1:8000/xmlhttprequest/resources/get.txt", true); 128 xhr.send(); 125 129 126 130 var id = 0; -
trunk/LayoutTests/http/tests/security/contentSecurityPolicy/source-list-parsing-malformed-meta.html
r133095 r199221 18 18 try { 19 19 var xhr = new XMLHttpRequest; 20 xhr.open("GET", "http://127.0.0.1:8000/xmlhttprequest/resources/get.txt", true); 20 xhr.open("GET", "http://127.0.0.1:8000/xmlhttprequest/resources/get.txt", false); 21 xhr.send(); 21 22 log("Fail"); 22 23 } catch(e) { -
trunk/LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr-expected.txt
r198591 r199221 1 CONSOLE MESSAGE: Refused to connect to http://localhost:8000/security/isolatedWorld/resources/cross-origin-xhr.txt because it does not appear in the connect-src directive of the Content Security Policy. 1 CONSOLE MESSAGE: Refused to connect to http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow.cgi because it does not appear in the connect-src directive of the Content Security Policy. 2 CONSOLE MESSAGE: Refused to connect to http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow.cgi because it does not appear in the connect-src directive of the Content Security Policy. 2 3 Tests that isolated worlds can have XHRs that the page's CSP wouldn't allow. 3 4 … … 5 6 6 7 7 XHR from main world 8 PASS: XHR.open threw an exception. 9 XHR from isolated world 10 PASS: XHR.open did not throw an exception. 8 Synchronous XHR same-origin from main world 9 PASS: XHR.send threw an exception. 10 Asynchronous XHR same-origin from main world 11 PASS: XHR.send did not throw an exception. 12 PASS: XHR.send received an error event. 13 Synchronous XHR same-origin from isolated world 14 PASS: XHR.send did not throw an exception. 15 Asynchronous XHR same-origin from isolated world 16 PASS: XHR.send did not throw an exception. 17 PASS: XHR.send received a load event. 18 Synchronous XHR cross-origin from isolated world 19 PASS: XHR.send did not throw an exception. 20 Asynchronous XHR cross-origin from isolated world 21 PASS: XHR.send did not throw an exception. 22 PASS: XHR.send received a load event. 11 23 PASS successfullyParsed is true 12 24 -
trunk/LayoutTests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-xhr.html
r148076 r199221 1 1 <!DOCTYPE html> 2 2 <html> 3 <head> 3 4 <script src="../../js-test-resources/js-test-pre.js"></script> 4 5 <meta http-equiv="Content-Security-Policy" content="connect-src 'none'"> 6 </head> 5 7 <body> 6 8 <p id="description"></p> … … 12 14 jsTestIsAsync = true; 13 15 16 const SameOrigin = true; 17 const CrossOrigin = false; 18 const Asynchronous = true; 19 const Synchronous = false; 20 const ShouldBlock = true; 21 const ShouldNotBlock = false; 22 14 23 var tests = [ 15 24 function() { 16 debug(' XHRfrom main world');17 xhr( true);25 debug('Synchronous XHR same-origin from main world'); 26 xhr({sameOrigin : true}, Synchronous, ShouldBlock); 18 27 }, 19 28 function() { 20 debug(' XHR from isolatedworld');21 runTestInWorld(1, 'xhr', 'false');29 debug('Asynchronous XHR same-origin from main world'); 30 xhr({sameOrigin : true}, Asynchronous, ShouldBlock); 22 31 }, 32 function() { 33 debug('Synchronous XHR same-origin from isolated world'); 34 invokeInWorld(1, xhr, SameOrigin, Synchronous, ShouldNotBlock); 35 }, 36 function() { 37 debug('Asynchronous XHR same-origin from isolated world'); 38 invokeInWorld(2, xhr, SameOrigin, Asynchronous, ShouldNotBlock); 39 }, 40 function() { 41 debug('Synchronous XHR cross-origin from isolated world'); 42 invokeInWorld(3, xhr, CrossOrigin, Synchronous, ShouldNotBlock); 43 }, 44 function() { 45 debug('Asynchronous XHR cross-origin from isolated world'); 46 invokeInWorld(4, xhr, CrossOrigin, Asynchronous, ShouldNotBlock); 47 } 23 48 ]; 24 49 var currentTest = 0; … … 53 78 } 54 79 55 function runTestInWorld(worldId, funcName, param) 56 { 57 testRunner.evaluateScriptInIsolatedWorld( 58 worldId, String(eval(funcName)) + "\n" + funcName + "(" + param + ");"); 80 // This function will only successfully pass on JSON-stringifieable arguments such as numbers and strings to aNamedFunction 81 function invokeInWorld(worldId, aNamedFunction) { 82 console.assert(aNamedFunction.name); 83 var argumentsToPass = Array.prototype.slice.call(arguments, 2); 84 var script = aNamedFunction.toString() + '; ' + aNamedFunction.name + '(' + argumentsToPass.map(JSON.stringify).join(', ') + ');'; 85 testRunner.evaluateScriptInIsolatedWorld(worldId, script); 59 86 } 60 87 61 function xhr(shouldBlock) 62 { 88 function xhr(isSameOrigin, isAsync, shouldBlock) { 63 89 function debug(message) { 64 90 window.postMessage(JSON.stringify({ … … 69 95 } 70 96 97 var url = (isSameOrigin ? 'http://127.0.0.1:8000/' : 'http://localhost:8000/') + 'xmlhttprequest/resources/access-control-basic-allow.cgi'; 71 98 var xhr = new XMLHttpRequest(); 99 var asyncCallDone = false; 100 var finallyClauseDone = false; 101 102 xhr.open('GET', url, isAsync); 103 104 if (isAsync) { 105 xhr.addEventListener('load', function() { 106 if (shouldBlock) 107 debug('FAIL: XHR.send should not have received a load event.'); 108 else 109 debug('PASS: XHR.send received a load event.'); 110 111 if (finallyClauseDone) 112 window.postMessage(JSON.stringify({'type': 'test-done'}), '*'); 113 else 114 asyncCallDone = true; 115 }); 116 117 xhr.addEventListener('error', function() { 118 if (shouldBlock) 119 debug('PASS: XHR.send received an error event.'); 120 else 121 debug('FAIL: XHR.send should not have received an error event.'); 122 123 if (finallyClauseDone) 124 window.postMessage(JSON.stringify({'type': 'test-done'}), '*'); 125 else 126 asyncCallDone = true; 127 }); 128 } 129 72 130 try { 73 xhr. open('GET', 'http://localhost:8000/security/isolatedWorld/resources/cross-origin-xhr.txt', true);74 if (shouldBlock )75 debug('FAIL: XHR. openshould have thrown an exception.');131 xhr.send(); 132 if (shouldBlock && !isAsync) 133 debug('FAIL: XHR.send should have thrown an exception.'); 76 134 else 77 debug('PASS: XHR. opendid not throw an exception.');135 debug('PASS: XHR.send did not throw an exception.'); 78 136 } catch (e) { 79 if (shouldBlock )80 debug('PASS: XHR. openthrew an exception.');137 if (shouldBlock && !isAsync) 138 debug('PASS: XHR.send threw an exception.'); 81 139 else 82 debug('FAIL: XHR. openshould not have thrown an exception.');140 debug('FAIL: XHR.send should not have thrown an exception.'); 83 141 } finally { 84 window.postMessage(JSON.stringify({'type': 'test-done'}), '*'); 142 if (!isAsync || asyncCallDone) 143 window.postMessage(JSON.stringify({'type': 'test-done'}), '*'); 144 else 145 finallyClauseDone = true; 85 146 } 86 147 } 87 88 148 </script> 89 90 149 <script src="../../js-test-resources/js-test-post.js"></script> 91 150 </body> -
trunk/Source/WebCore/ChangeLog
r199216 r199221 1 2016-04-08 John Wilander <wilander@apple.com> 2 3 CSP: Block XHR when calling XMLHttpRequest.send() and throw network error. 4 https://bugs.webkit.org/show_bug.cgi?id=153598 5 <rdar://problem/24391483> 6 7 Reviewed by Darin Adler. 8 9 No new tests. Changes to existing tests are sufficient. 10 11 * xml/XMLHttpRequest.cpp: 12 (WebCore::XMLHttpRequest::open): 13 (WebCore::XMLHttpRequest::initSend): 14 Moved the CSP check from XMLHttpRequest::open() to XMLHttpRequest::initSend(). 15 Changed the thrown error type from Security to Network for synchronous requests. 16 Changed from throwing an error to firing an error event for asynchronous requests. 17 These changes are in conformance with connect-src of Content Security Policy Level 2. 18 https://www.w3.org/TR/CSP2/#directive-connect-src (W3C Candidate Recommendation, 21 July 2015) 19 1 20 2016-04-07 Darin Adler <darin@apple.com> 2 21 -
trunk/Source/WebCore/xml/XMLHttpRequest.cpp
r198869 r199221 498 498 } 499 499 500 // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved.501 if (!scriptExecutionContext()->contentSecurityPolicy()->allowConnectToSource(url, scriptExecutionContext()->shouldBypassMainWorldContentSecurityPolicy())) {502 // FIXME: Should this be throwing an exception?503 ec = SECURITY_ERR;504 return;505 }506 507 500 if (!async && scriptExecutionContext()->isDocument()) { 508 501 if (document()->settings() && !document()->settings()->syncXHRInDocumentsEnabled()) { … … 573 566 } 574 567 ASSERT(!m_loader); 568 569 // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved. 570 if (!scriptExecutionContext()->contentSecurityPolicy()->allowConnectToSource(m_url, scriptExecutionContext()->shouldBypassMainWorldContentSecurityPolicy())) { 571 if (m_async) { 572 setPendingActivity(this); 573 m_timeoutTimer.stop(); 574 m_networkErrorTimer.startOneShot(0); 575 } else 576 ec = NETWORK_ERR; 577 return false; 578 } 575 579 576 580 m_error = false;
Note: See TracChangeset
for help on using the changeset viewer.