diff --git a/dom/base/nsXMLHttpRequest.cpp b/dom/base/nsXMLHttpRequest.cpp index 969652703132..1bc30c752ac5 100644 --- a/dom/base/nsXMLHttpRequest.cpp +++ b/dom/base/nsXMLHttpRequest.cpp @@ -1690,10 +1690,8 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url, nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; } - // If we have the document, use it. Unfortunately, for dedicated workers - // 'doc' ends up being the parent document, which is not the document - // that we want to use. So make sure to avoid using 'doc' in that situation. - if (doc && doc->NodePrincipal() == mPrincipal) { + // If we have the document, use it + if (doc) { rv = NS_NewChannel(getter_AddRefs(mChannel), uri, doc, diff --git a/dom/security/test/csp/file_main.html^headers^ b/dom/security/test/csp/file_main.html^headers^ index 3338de389b31..c7fdbae20471 100644 --- a/dom/security/test/csp/file_main.html^headers^ +++ b/dom/security/test/csp/file_main.html^headers^ @@ -1 +1 @@ -Content-Security-Policy: default-src 'self' blob: ; style-src 'unsafe-inline' 'self' +Content-Security-Policy: default-src 'self' ; style-src 'unsafe-inline' 'self' diff --git a/dom/security/test/csp/file_main.js b/dom/security/test/csp/file_main.js index 0bc15b6827a4..864a5d230b95 100644 --- a/dom/security/test/csp/file_main.js +++ b/dom/security/test/csp/file_main.js @@ -1,28 +1,16 @@ -function doXHR(uri) { - try { - var xhr = new XMLHttpRequest(); - xhr.open("GET", uri); - xhr.send(); - } catch(ex) {} -} +// some javascript for the CSP XHR tests +// -doXHR("http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=xhr_good"); -doXHR("http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=xhr_bad"); -fetch("http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=fetch_good"); -fetch("http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=fetch_bad"); -navigator.sendBeacon("http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=beacon_good"); try { - navigator.sendBeacon("http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=beacon_bad"); -} catch(ex) {} + var xhr_good = new XMLHttpRequest(); + var xhr_good_uri ="http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=xhr_good"; + xhr_good.open("GET", xhr_good_uri, true); + xhr_good.send(null); +} catch(e) {} - -new Worker("file_main_worker.js").postMessage({inherited : false}); - - -var blobxhr = new XMLHttpRequest(); -blobxhr.open("GET", "file_main_worker.js") -blobxhr.responseType = "blob"; -blobxhr.send(); -blobxhr.onload = () => { - new Worker(URL.createObjectURL(blobxhr.response)).postMessage({inherited : true}); -} +try { + var xhr_bad = new XMLHttpRequest(); + var xhr_bad_uri ="http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=xhr_bad"; + xhr_bad.open("GET", xhr_bad_uri, true); + xhr_bad.send(null); +} catch(e) {} diff --git a/dom/security/test/csp/file_main_worker.js b/dom/security/test/csp/file_main_worker.js deleted file mode 100644 index d8953eec7489..000000000000 --- a/dom/security/test/csp/file_main_worker.js +++ /dev/null @@ -1,28 +0,0 @@ -function doXHR(uri) { - try { - var xhr = new XMLHttpRequest(); - xhr.open("GET", uri); - xhr.send(); - } catch(ex) {} -} - -var sameBase = "http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid="; -var crossBase = "http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid="; - -onmessage = (e) => { - for (base of [sameBase, crossBase]) { - var prefix; - var suffix; - if (e.data.inherited) { - prefix = base + "worker_inherited_" - suffix = base == sameBase ? "_good" : "_bad"; - } - else { - prefix = base + "worker_" - suffix = base == sameBase ? "_same_good" : "_cross_good"; - } - doXHR(prefix + "xhr" + suffix); - fetch(prefix + "fetch" + suffix); - try { importScripts(prefix + "script" + suffix); } catch(ex) {} - } -} diff --git a/dom/security/test/csp/file_redirects_main.html b/dom/security/test/csp/file_redirects_main.html index 5c9affea04ba..651f44d38495 100644 --- a/dom/security/test/csp/file_redirects_main.html +++ b/dom/security/test/csp/file_redirects_main.html @@ -11,18 +11,17 @@ var thisSite = "http://mochi.test:8888"; var otherSite = "http://example.com"; var page = "/tests/dom/security/test/csp/file_redirects_page.sjs"; -var tests = { "font-src": thisSite+page+"?testid=font-src", - "frame-src": thisSite+page+"?testid=frame-src", - "img-src": thisSite+page+"?testid=img-src", - "media-src": thisSite+page+"?testid=media-src", - "object-src": thisSite+page+"?testid=object-src", - "script-src": thisSite+page+"?testid=script-src", - "style-src": thisSite+page+"?testid=style-src", - "worker": thisSite+page+"?testid=worker", - "xhr-src": thisSite+page+"?testid=xhr-src", - "from-worker": thisSite+page+"?testid=from-worker", - "from-blob-worker": thisSite+page+"?testid=from-blob-worker", - "img-src-from-css": thisSite+page+"?testid=img-src-from-css", +var tests = { "font-src": thisSite+page+"?testid=font-src&csp=1", + "frame-src": thisSite+page+"?testid=frame-src&csp=1", + "img-src": thisSite+page+"?testid=img-src&csp=1", + "media-src": thisSite+page+"?testid=media-src&csp=1", + "object-src": thisSite+page+"?testid=object-src&csp=1", + "script-src": thisSite+page+"?testid=script-src&csp=1", + "style-src": thisSite+page+"?testid=style-src&csp=1", + "worker": thisSite+page+"?testid=worker&csp=1", + "xhr-src": thisSite+page+"?testid=xhr-src&csp=1", + "script-src-from-worker": thisSite+page+"?testid=script-src-from-worker&csp=1", + "img-src-from-css": thisSite+page+"?testid=img-src-from-css&csp=1", }; var container = document.getElementById("container"); diff --git a/dom/security/test/csp/file_redirects_page.sjs b/dom/security/test/csp/file_redirects_page.sjs index 9e3c0d0350d4..a849185d5c7f 100644 --- a/dom/security/test/csp/file_redirects_page.sjs +++ b/dom/security/test/csp/file_redirects_page.sjs @@ -14,13 +14,15 @@ function handleRequest(request, response) var resource = "/tests/dom/security/test/csp/file_redirects_resource.sjs"; // CSP header value - var additional = "" - if (query['testid'] == "worker") { - additional = "; script-src 'self' 'unsafe-inline'"; + if (query["csp"] == 1) { + var additional = "" + if (query['testid'] == "worker") { + additional = "; script-src 'self' 'unsafe-inline'"; + } + response.setHeader("Content-Security-Policy", + "default-src 'self' ; style-src 'self' 'unsafe-inline'" + additional, + false); } - response.setHeader("Content-Security-Policy", - "default-src 'self' blob: ; style-src 'self' 'unsafe-inline'" + additional, - false); // downloadable font that redirects to another site if (query["testid"] == "font-src") { @@ -88,27 +90,13 @@ function handleRequest(request, response) return; } - if (query["testid"] == "from-worker") { + if (query["testid"] == "script-src-from-worker") { // loads a script; launches a worker; that worker uses importscript; which then gets redirected // So it's: - // '); - return; - } - - if (query["testid"] == "from-blob-worker") { - // loads a script; launches a worker; that worker uses importscript; which then gets redirected - // So it's: - // '); + response.write(''); return; } } diff --git a/dom/security/test/csp/file_redirects_resource.sjs b/dom/security/test/csp/file_redirects_resource.sjs index d281f19d8ba5..b23be2f512dd 100644 --- a/dom/security/test/csp/file_redirects_resource.sjs +++ b/dom/security/test/csp/file_redirects_resource.sjs @@ -102,45 +102,29 @@ function handleRequest(request, response) // script that loads an internal worker that uses importScripts on a redirect // to an external script. - if (query["res"] == "loadWorkerThatMakesRequests") { + if (query["res"] == "loadWorkerThatImports") { // this creates a worker (same origin) that imports a redirecting script. - let workerURL = thisSite + resource + '?res=makeRequestsWorker&id=' + query["id"]; + let workerURL = thisSite + resource + '?res=importScriptWorker&id=' + query["id"]; response.setHeader("Content-Type", "application/javascript", false); - response.write("new Worker('" + workerURL + "');"); - return; - } - - // script that loads an internal worker that uses importScripts on a redirect - // to an external script. - if (query["res"] == "loadBlobWorkerThatMakesRequests") { - // this creates a worker (same origin) that imports a redirecting script. - let workerURL = thisSite + resource + '?res=makeRequestsWorker&id=' + query["id"]; - response.setHeader("Content-Type", "application/javascript", false); - response.write("var x = new XMLHttpRequest(); x.open('GET', '" + workerURL + "'); "); - response.write("x.responseType = 'blob'; x.send(); "); - response.write("x.onload = () => { new Worker(URL.createObjectURL(x.response)); };"); + response.write("var w=new Worker('" + workerURL + "'); w.onmessage=function(event){ alert(event.data); }"); return; } // source for a worker that simply calls importScripts on a script that // redirects. - if (query["res"] == "makeRequestsWorker") { + if (query["res"] == "importScriptWorker") { // this is code for a worker that imports a redirected script. - let scriptURL = thisSite + resource + "?redir=other&res=script&id=script-src-redir-" + query["id"]; - let xhrURL = thisSite + resource + "?redir=other&res=xhr-resp&id=xhr-src-redir-" + query["id"]; - let fetchURL = thisSite + resource + "?redir=other&res=xhr-resp&id=fetch-src-redir-" + query["id"]; + let scriptURL = thisSite + resource + "?redir=other&res=script&id=" + query["id"]; response.setHeader("Content-Type", "application/javascript", false); - response.write("try { importScripts('" + scriptURL + "'); } catch(ex) {} "); - response.write("var x = new XMLHttpRequest(); x.open('GET', '" + xhrURL + "'); x.send();"); - response.write("fetch('" + fetchURL + "');"); + response.write("importScripts('" + scriptURL + "');"); return; } // script that invokes XHR if (query["res"] == "xhr") { response.setHeader("Content-Type", "application/javascript", false); - var resp = 'var x = new XMLHttpRequest();x.open("GET", "' + thisSite + - resource+'?redir=other&res=xhr-resp&id=xhr-src-redir", false);\n' + + var resp = 'var x = new XMLHttpRequest();x.open("GET", "' + otherSite + + resource+'?res=xhr-resp&testid=xhr-src-redir", false);\n' + 'x.send(null);'; response.write(resp); return; diff --git a/dom/security/test/csp/file_worker_redirect.html b/dom/security/test/csp/file_worker_redirect.html new file mode 100644 index 000000000000..be80f5795f8c --- /dev/null +++ b/dom/security/test/csp/file_worker_redirect.html @@ -0,0 +1,9 @@ + + + + Bug 949706 - CSP: Correct handling of web workers importing scripts that get redirected + + + + + diff --git a/dom/security/test/csp/file_worker_redirect.sjs b/dom/security/test/csp/file_worker_redirect.sjs new file mode 100644 index 000000000000..6c4acd6e7a27 --- /dev/null +++ b/dom/security/test/csp/file_worker_redirect.sjs @@ -0,0 +1,37 @@ +// testserver customized for the needs of: +// Bug 949706 - CSP: Correct handling of web workers importing scripts that get redirected + +function handleRequest(request, response) +{ + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html", false); + + var query = request.queryString; + + if (query === "stage_0_script_loads_worker") { + var newWorker = + "var myWorker = new Worker(\"file_worker_redirect.sjs?stage_1_worker_import_scripts\");" + + "myWorker.onmessage = function (event) { parent.checkResult(\"allowed\"); };" + + "myWorker.onerror = function (event) { parent.checkResult(\"blocked\"); };"; + response.write(newWorker); + return; + } + + if (query === "stage_1_worker_import_scripts") { + response.write("importScripts(\"file_worker_redirect.sjs?stage_2_redirect_imported_script\");"); + return; + } + + if (query === "stage_2_redirect_imported_script") { + var newLocation = + "http://test1.example.com/tests/dom/security/test/csp/file_worker_redirect.sjs?stage_3_target_script"; + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", newLocation, false); + return; + } + + if (query === "stage_3_target_script") { + response.write("postMessage(\"imported script loaded\");"); + return; + } +} diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini index 0b8dc68bdcca..94966a778c2c 100644 --- a/dom/security/test/csp/mochitest.ini +++ b/dom/security/test/csp/mochitest.ini @@ -40,7 +40,6 @@ support-files = file_main.html file_main.html^headers^ file_main.js - file_main_worker.js file_web_manifest.html file_web_manifest_remote.html file_web_manifest_https.html @@ -116,6 +115,8 @@ support-files = file_multi_policy_injection_bypass_2.html^headers^ file_null_baseuri.html file_form-action.html + file_worker_redirect.html + file_worker_redirect.sjs file_referrerdirective.html referrerdirective.sjs file_upgrade_insecure.html @@ -198,6 +199,7 @@ skip-if = buildapp == 'b2g' # intermittent orange (bug 1028490) [test_referrerdirective.html] skip-if = buildapp == 'b2g' #no ssl support [test_dual_header.html] +[test_worker_redirect.html] [test_upgrade_insecure.html] # no ssl support as well as websocket tests do not work (see test_websocket.html) skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android' diff --git a/dom/security/test/csp/test_CSP.html b/dom/security/test/csp/test_CSP.html index 253ea8d3a769..2b508bd0d19a 100644 --- a/dom/security/test/csp/test_CSP.html +++ b/dom/security/test/csp/test_CSP.html @@ -25,22 +25,6 @@ window.tests = { script_bad: -1, xhr_good: -1, xhr_bad: -1, - fetch_good: -1, - fetch_bad: -1, - beacon_good: -1, - beacon_bad: -1, - worker_xhr_same_good: -1, - worker_xhr_cross_good: -1, - worker_fetch_same_good: -1, - worker_fetch_cross_good: -1, - worker_script_same_good: -1, - worker_script_cross_good: -1, - worker_inherited_xhr_good: -1, - worker_inherited_xhr_bad: -1, - worker_inherited_fetch_good: -1, - worker_inherited_fetch_bad: -1, - worker_inherited_script_good: -1, - worker_inherited_script_bad: -1, media_good: -1, media_bad: -1, font_good: -1, @@ -97,11 +81,10 @@ examiner.prototype = { window.examiner = new examiner(); window.testResult = function(testname, result, msg) { - // test already complete.... forget it... remember the first result. + //test already complete.... forget it... remember the first result. if (window.tests[testname] != -1) return; - ok(testname in window.tests, "It's a real test"); window.tests[testname] = result; is(result, true, testname + ' test: ' + msg); diff --git a/dom/security/test/csp/test_redirects.html b/dom/security/test/csp/test_redirects.html index 4a588dcbe111..4656dd70deef 100644 --- a/dom/security/test/csp/test_redirects.html +++ b/dom/security/test/csp/test_redirects.html @@ -86,16 +86,10 @@ var testExpectedResults = { "font-src": true, "worker-redir": false, "xhr-src": true, "xhr-src-redir": false, - "from-worker": true, - "script-src-redir-from-worker": true, /* redir is allowed since policy isn't inherited */ - "xhr-src-redir-from-worker": true, /* redir is allowed since policy isn't inherited */ - "fetch-src-redir-from-worker": true, /* redir is allowed since policy isn't inherited */ - "from-blob-worker": true, - "script-src-redir-from-blob-worker": false, - "xhr-src-redir-from-blob-worker": false, - "fetch-src-redir-from-blob-worker": false, - "img-src-from-css": true, - "img-src-redir-from-css": false, + "script-src-from-worker": true, /* test runs */ + "script-src-redir-from-worker": false, /* redir is blocked */ + "img-src-from-css": true, /* test runs */ + "img-src-redir-from-css": false, /* redir is blocked */ }; // takes the name of the test, the URL that was tested, and whether the diff --git a/dom/security/test/csp/test_worker_redirect.html b/dom/security/test/csp/test_worker_redirect.html new file mode 100644 index 000000000000..b45ce3823186 --- /dev/null +++ b/dom/security/test/csp/test_worker_redirect.html @@ -0,0 +1,76 @@ + + + + Bug 949706 - CSP: Correct handling of web workers importing scripts that get redirected + + + + + + + + + + diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp index 081c4d016edb..ee2b0c69f0f3 100644 --- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -122,14 +122,6 @@ ChannelFromScriptURL(nsIPrincipal* principal, return NS_ERROR_DOM_SYNTAX_ERR; } - // If we have the document, use it. Unfortunately, for dedicated workers - // 'parentDoc' ends up being the parent document, which is not the document - // that we want to use. So make sure to avoid using 'parentDoc' in that - // situation. - if (parentDoc && parentDoc->NodePrincipal() != principal) { - parentDoc = nullptr; - } - int16_t shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(aContentPolicyType, uri, principal, parentDoc, @@ -172,11 +164,8 @@ ChannelFromScriptURL(nsIPrincipal* principal, aLoadFlags |= nsIChannel::LOAD_CLASSIFY_URI; nsCOMPtr channel; - // If we have the document, use it. Unfortunately, for dedicated workers - // 'parentDoc' ends up being the parent document, which is not the document - // that we want to use. So make sure to avoid using 'parentDoc' in that - // situation. - if (parentDoc && parentDoc->NodePrincipal() == principal) { + // If we have the document, use it + if (parentDoc) { rv = NS_NewChannel(getter_AddRefs(channel), uri, parentDoc,