diff options
author | Moonchild <mcwerewolf@gmail.com> | 2018-06-24 14:11:54 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-24 14:11:54 +0200 |
commit | 364a399fc1157f73b8a29039a9e7f8d8b7028df5 (patch) | |
tree | 1ba580e017e0f428b6bb33a7872d520d6a9c8928 | |
parent | 574156323b4fb817c1eb62f442b4e3cbdec9067b (diff) | |
parent | 0097345ad9aa859dcf02cb0ba80685d51bc7ec16 (diff) | |
download | UXP-364a399fc1157f73b8a29039a9e7f8d8b7028df5.tar UXP-364a399fc1157f73b8a29039a9e7f8d8b7028df5.tar.gz UXP-364a399fc1157f73b8a29039a9e7f8d8b7028df5.tar.lz UXP-364a399fc1157f73b8a29039a9e7f8d8b7028df5.tar.xz UXP-364a399fc1157f73b8a29039a9e7f8d8b7028df5.zip |
Merge pull request #540 from janekptacijarabaci/security_csp_script_redirect_1
Fix CSP: Scripts with valid nonce should not be blocked if URL redirects
-rw-r--r-- | dom/security/nsCSPService.cpp | 5 | ||||
-rw-r--r-- | dom/security/test/csp/file_nonce_redirector.sjs | 25 | ||||
-rw-r--r-- | dom/security/test/csp/file_nonce_redirects.html | 23 | ||||
-rw-r--r-- | dom/security/test/csp/mochitest.ini | 3 | ||||
-rw-r--r-- | dom/security/test/csp/test_nonce_redirects.html | 47 | ||||
-rw-r--r-- | netwerk/base/LoadInfo.cpp | 23 | ||||
-rw-r--r-- | netwerk/base/nsILoadInfo.idl | 17 |
7 files changed, 139 insertions, 4 deletions
diff --git a/dom/security/nsCSPService.cpp b/dom/security/nsCSPService.cpp index 7344e19fa..4807c9aa4 100644 --- a/dom/security/nsCSPService.cpp +++ b/dom/security/nsCSPService.cpp @@ -288,6 +288,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsContentUtils::InternalContentPolicyTypeToExternalOrWorker(policyType); int16_t aDecision = nsIContentPolicy::ACCEPT; + nsCOMPtr<nsISupports> requestContext = loadInfo->GetLoadingContext(); // 1) Apply speculative CSP for preloads if (isPreload) { nsCOMPtr<nsIContentSecurityPolicy> preloadCsp; @@ -298,7 +299,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel, preloadCsp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t) newUri, // nsIURI nullptr, // nsIURI - nullptr, // nsISupports + requestContext, // nsISupports EmptyCString(), // ACString - MIME guess originalUri, // aExtra &aDecision); @@ -321,7 +322,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel, csp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t) newUri, // nsIURI nullptr, // nsIURI - nullptr, // nsISupports + requestContext, // nsISupports EmptyCString(), // ACString - MIME guess originalUri, // aExtra &aDecision); diff --git a/dom/security/test/csp/file_nonce_redirector.sjs b/dom/security/test/csp/file_nonce_redirector.sjs new file mode 100644 index 000000000..21a8f4e9c --- /dev/null +++ b/dom/security/test/csp/file_nonce_redirector.sjs @@ -0,0 +1,25 @@ +// custom *.sjs file for +// Bug 1469150:Scripts with valid nonce get blocked if URL redirects. + +const URL_PATH = "example.com/tests/dom/security/test/csp/"; + +function handleRequest(request, response) { + response.setHeader("Cache-Control", "no-cache", false); + let queryStr = request.queryString; + + if (queryStr === "redirect") { + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", + "https://" + URL_PATH + "file_nonce_redirector.sjs?load", false); + return; + } + + if (queryStr === "load") { + response.setHeader("Content-Type", "application/javascript", false); + response.write("console.log('script loaded');"); + return; + } + + // we should never get here - return something unexpected + response.write("d'oh"); +} diff --git a/dom/security/test/csp/file_nonce_redirects.html b/dom/security/test/csp/file_nonce_redirects.html new file mode 100644 index 000000000..e29116490 --- /dev/null +++ b/dom/security/test/csp/file_nonce_redirects.html @@ -0,0 +1,23 @@ +<!DOCTYPE HTML> +<html> + <head> + <meta charset='utf-8'> + <meta http-equiv="Content-Security-Policy" content="script-src 'nonce-abcd1234'"> + <title>Bug 1469150:Scripts with valid nonce get blocked if URL redirects</title> + </head> +<body> + +<script nonce='abcd1234' id='redirectScript'></script> + +<script nonce='abcd1234' type='application/javascript'> + var redirectScript = document.getElementById('redirectScript'); + redirectScript.onload = function(e) { + window.parent.postMessage({result: 'script-loaded'}, '*'); + }; + redirectScript.onerror = function(e) { + window.parent.postMessage({result: 'script-blocked'}, '*'); + } + redirectScript.src = 'file_nonce_redirector.sjs?redirect'; +</script> +</body> +</html> diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini index 33b112020..86b7fd0cd 100644 --- a/dom/security/test/csp/mochitest.ini +++ b/dom/security/test/csp/mochitest.ini @@ -88,6 +88,8 @@ support-files = file_shouldprocess.html file_nonce_source.html file_nonce_source.html^headers^ + file_nonce_redirects.html + file_nonce_redirector.sjs file_bug941404.html file_bug941404_xhr.html file_bug941404_xhr.html^headers^ @@ -245,6 +247,7 @@ skip-if = toolkit == 'android' # Times out, not sure why (bug 1008445) [test_frame_ancestors_ro.html] [test_policyuri_regression_from_multipolicy.html] [test_nonce_source.html] +[test_nonce_redirects.html] [test_bug941404.html] [test_form-action.html] [test_hash_source.html] diff --git a/dom/security/test/csp/test_nonce_redirects.html b/dom/security/test/csp/test_nonce_redirects.html new file mode 100644 index 000000000..f84fdcc7b --- /dev/null +++ b/dom/security/test/csp/test_nonce_redirects.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Bug 1469150:Scripts with valid nonce get blocked if URL redirects</title> + <!-- Including SimpleTest.js so we can use waitForExplicitFinish !--> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<iframe style="width:100%;" id="testframe"></iframe> + +<script class="testbody" type="text/javascript"> + +/* Description of the test: + * We load a script with a matching nonce, which redirects + * and we make sure that script is allowed. + */ + +SimpleTest.waitForExplicitFinish(); + +function finishTest() { + window.removeEventListener("message", receiveMessage); + SimpleTest.finish(); +} + +function checkResults(aResult) { + + if (aResult === "script-loaded") { + ok(true, "expected result: script loaded"); + } + else { + ok(false, "unexpected result: script blocked"); + } + finishTest(); +} + +window.addEventListener("message", receiveMessage); +function receiveMessage(event) { + checkResults(event.data.result); +} + +document.getElementById("testframe").src = "file_nonce_redirects.html"; + +</script> +</body> +</html> diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index a8c9a5a25..ebe9d4703 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -81,7 +81,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, // This constructor shouldn't be used for TYPE_DOCUMENT loads that don't // have a loadingPrincipal - MOZ_ASSERT(skipContentTypeCheck || + MOZ_ASSERT(skipContentTypeCheck || mLoadingPrincipal || mInternalContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT); // TODO(bug 1259873): Above, we initialize mIsThirdPartyContext to false meaning @@ -493,6 +493,27 @@ LoadInfo::ContextForTopLevelLoad() return context; } +already_AddRefed<nsISupports> +LoadInfo::GetLoadingContext() +{ + nsCOMPtr<nsISupports> context; + if (mInternalContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) { + context = ContextForTopLevelLoad(); + } + else { + context = LoadingNode(); + } + return context.forget(); +} + +NS_IMETHODIMP +LoadInfo::GetLoadingContextXPCOM(nsISupports** aResult) +{ + nsCOMPtr<nsISupports> context = GetLoadingContext(); + context.forget(aResult); + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetSecurityFlags(nsSecurityFlags* aResult) { diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 9a883ff98..bc609c317 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -10,7 +10,7 @@ interface nsIDOMDocument; interface nsINode; interface nsIPrincipal; - +native LoadContextRef(already_AddRefed<nsISupports>); %{C++ #include "nsTArray.h" #include "mozilla/BasePrincipal.h" @@ -334,6 +334,21 @@ interface nsILoadInfo : nsISupports nsISupports binaryContextForTopLevelLoad(); /** + * For all loads except loads of TYPE_DOCUMENT, the loadingContext + * simply returns the loadingNode. For loads of TYPE_DOCUMENT this + * will return the context available for top-level loads which + * do not have a loadingNode. + */ + [binaryname(LoadingContextXPCOM)] + readonly attribute nsISupports loadingContext; + + /** + * A C++ friendly version of the loadingContext. + */ + [noscript, notxpcom, nostdcall, binaryname(GetLoadingContext)] + LoadContextRef binaryGetLoadingContext(); + + /** * The securityFlags of that channel. */ readonly attribute nsSecurityFlags securityFlags; |