Bug 1505412 - Skip CSP-Nonce check for CSP-Ro+Redirected Channels r=ckerschb
☠☠ backed out by 170d5cc410a4 ☠ ☠
authorSebastian Streich <sstreich@mozilla.com>
Thu, 15 Aug 2019 15:51:33 +0000
changeset 488463 983ff93a11ad7c08fd65a507dedf01526e4ae682
parent 488462 a550b308d88ae8e6bbdd1bab0123028ca98512d8
child 488464 36d75347441bbeaf2f9f3e321f6318d7643ccec2
push id92761
push userarchaeopteryx@coole-files.de
push dateFri, 16 Aug 2019 08:13:25 +0000
treeherderautoland@983ff93a11ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb
bugs1505412
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1505412 - Skip CSP-Nonce check for CSP-Ro+Redirected Channels r=ckerschb Differential Revision: https://phabricator.services.mozilla.com/D36916
dom/security/nsCSPUtils.cpp
dom/security/test/csp/file_bug1505412.sjs
dom/security/test/csp/file_bug1505412_chrome.js
dom/security/test/csp/file_bug1505412_frame.html
dom/security/test/csp/file_bug1505412_frame.html^headers^
dom/security/test/csp/mochitest.ini
dom/security/test/csp/test_bug1505412.html
--- a/dom/security/nsCSPUtils.cpp
+++ b/dom/security/nsCSPUtils.cpp
@@ -872,16 +872,35 @@ bool nsCSPNonceSrc::permits(nsIURI* aUri
                             bool aWasRedirected, bool aReportOnly,
                             bool aUpgradeInsecure, bool aParserCreated) const {
   if (CSPUTILSLOGENABLED()) {
     CSPUTILSLOG(("nsCSPNonceSrc::permits, aUri: %s, aNonce: %s",
                  aUri->GetSpecOrDefault().get(),
                  NS_ConvertUTF16toUTF8(aNonce).get()));
   }
 
+  if (aReportOnly && aWasRedirected && aNonce.IsEmpty()) {
+    /* Fix for Bug 1505412
+     *  If we land here, we're currently handling a script-preload which got
+     *  redirected. Preloads do not have any info about the nonce assiociated.
+     *  Because of Report-Only the preload passes the 1st CSP-check so the
+     *  preload does not get retried with a nonce attached.
+     *  Currently we're relying on the script-manager to
+     *  provide a fake loadinfo to check the preloads against csp.
+     *  So during HTTPChannel->OnRedirect we cant check csp for this case.
+     *  But as the script-manager already checked the csp,
+     *  a report would already have been send,
+     *  if the nonce didnt match.
+     *  So we can pass the check here for Report-Only Cases.
+     */
+    MOZ_ASSERT(aParserCreated == false,
+               "Skipping nonce-check is only allowed for Preloads");
+    return true;
+  }
+
   // nonces can not be invalidated by strict-dynamic
   return mNonce.Equals(aNonce);
 }
 
 bool nsCSPNonceSrc::allows(enum CSPKeyword aKeyword,
                            const nsAString& aHashOrNonce,
                            bool aParserCreated) const {
   CSPUTILSLOG(("nsCSPNonceSrc::allows, aKeyWord: %s, a HashOrNonce: %s",
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_bug1505412.sjs
@@ -0,0 +1,37 @@
+// https://bugzilla.mozilla.org/show_bug.cgi?id=650386
+// This SJS file serves file_redirect_content.html
+// with a CSP that will trigger a violation and that will report it
+// to file_redirect_report.sjs
+//
+// This handles 301, 302, 303 and 307 redirects. The HTTP status code
+// returned/type of redirect to do comes from the query string
+// parameter passed in from the test_bug650386_* files and then also
+// uses that value in the report-uri parameter of the CSP
+function handleRequest(request, response) {
+  response.setHeader("Cache-Control", "no-cache", false);
+
+  // this gets used in the CSP as part of the report URI.
+  var redirect = request.queryString;
+
+  if (!redirect) {
+    // if we somehow got some bogus redirect code here,
+    // do a 302 redirect to the same URL as the report URI
+    // redirects to - this will fail the test.
+    var loc =
+      "http://sub1.test1.example.org/tests/dom/security/test/csp/file_bug1505412.sjs?redirected";
+    response.setStatusLine("1.1", 302, "Found");
+    response.setHeader("Location", loc, false);
+    return;
+  }
+
+  // response.setHeader("content-type", "text/application", false);
+  // the actual file content.
+  // this image load will (intentionally) fail due to the CSP policy of default-src: 'self'
+  // specified by the CSP string above.
+  var content =
+    "ok(true,'Did load the redirected Script without throwing a CSP-Violation');  SimpleTest.finish();";
+
+  response.write(content);
+
+  return;
+}
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_bug1505412_chrome.js
@@ -0,0 +1,30 @@
+const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
+
+Cu.importGlobalProperties(["TextDecoder"]);
+
+var openingObserver = {
+  observe: function(subject, topic, data) {
+    sendAsyncMessage("request-found", { subject, topic, data });
+    // subject should be an nsURI
+    if (subject.QueryInterface == undefined) {
+      return;
+    }
+
+    if (topic == "http-on-opening-request") {
+      var asciiSpec = subject.QueryInterface(Ci.nsIHttpChannel).URI.asciiSpec;
+      sendAsyncMessage("request-found", asciiSpec);
+      if (!asciiSpec.includes("report")) {
+        return;
+      }
+      sendAsyncMessage("report-found");
+    }
+  },
+};
+
+Services.obs.addObserver(openingObserver, "http-on-opening-request");
+addMessageListener("finish", function() {
+  Services.obs.removeObserver(openingObserver, "http-on-opening-request");
+});
+
+sendAsyncMessage("proxy-ready");
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_bug1505412_frame.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+
+<head>
+    <title> Bug 1505412 CSP-RO reports violations in inline-scripts with nonce</title>
+    <script src="/tests/SimpleTest/SimpleTest.js" nonce="foobar"></script>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ 
+
+<body>
+    <script src="file_bug1505412.sjs" nonce="foobar"></script>
+</body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_bug1505412_frame.html^headers^
@@ -0,0 +1,1 @@
+Content-Security-Policy-Report-Only: script-src 'nonce-foobar'; report-uri /report/
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -82,16 +82,20 @@ support-files =
   file_bug909029_none.html
   file_bug909029_none.html^headers^
   file_bug1229639.html
   file_bug1229639.html^headers^
   file_bug1312272.html
   file_bug1312272.js
   file_bug1312272.html^headers^
   file_bug1452037.html
+  file_bug1505412.sjs
+  file_bug1505412_chrome.js
+  file_bug1505412_frame.html
+  file_bug1505412_frame.html^headers^
   file_policyuri_regression_from_multipolicy.html
   file_policyuri_regression_from_multipolicy.html^headers^
   file_policyuri_regression_from_multipolicy_policy
   file_nonce_source.html
   file_nonce_source.html^headers^
   file_nonce_redirects.html
   file_nonce_redirector.sjs
   file_bug941404.html
@@ -241,16 +245,17 @@ prefs =
 [test_connect-src.html]
 [test_CSP.html]
 [test_bug1452037.html]
 [test_allow_https_schemes.html]
 [test_bug663567.html]
 [test_bug802872.html]
 [test_bug885433.html]
 [test_bug888172.html]
+[test_bug1505412.html]
 [test_evalscript.html]
 [test_evalscript_blocked_by_strict_dynamic.html]
 [test_evalscript_allowed_by_strict_dynamic.html]
 [test_frameancestors.html]
 skip-if = fission
 [test_frameancestors_userpass.html]
 skip-if = fission || toolkit == 'android' # Times out, not sure why (bug 1008445)
 [test_inlinescript.html]
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/test_bug1505412.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+
+<head>
+    <title> Bug 1505412 CSP-RO reports violations in inline-scripts with nonce</title>
+    <script src="/tests/SimpleTest/SimpleTest.js" nonce="foobar"></script>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ 
+
+<body>
+    <p id="display"></p>
+    <div id="content" style="display: none">
+    </div>
+
+    <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1505412">Test for 1505412 </a>
+    <script class="testbody" type="text/javascript" nonce="foobar">
+    /* Description of the test:
+        1:  We setup a Proxy that will cause the Test to Fail
+            if Firefox sends a CSP-Report to /report
+        2:  We Load an iframe with has a Script pointing to
+            file_bug1505412.sjs 
+        3:  The Preloader will fetch the file and Gets redirected
+        4:  If correct, the File should be loaded and no CSP-Report 
+            should be send.  
+    */
+
+    
+
+        SimpleTest.waitForExplicitFinish();
+        SimpleTest.requestCompleteLog();
+        
+        var chromeScriptUrl = SimpleTest.getTestFileURL("file_bug1505412_chrome.js");
+        var script = SpecialPowers.loadChromeScript(chromeScriptUrl);
+
+        script.addMessageListener('proxy-ready', function pr() {
+            window.addEventListener("load",()=>{
+                document.querySelector("#target").src = "file_bug1505412_frame.html";
+            });
+        });
+
+
+        script.addMessageListener('report-found', function ml(msg) {
+            ok(false,"A report was triggered");
+            SimpleTest.finish();
+        });
+
+        
+        SimpleTest.registerCleanupFunction(()=>{
+            script.sendAsyncMessage("finish");
+        });
+
+    </script>
+    <iframe id="target" frameborder="0"></iframe>
+</body>
+
+</html>