Bug 1514680 - Strictly enforce the MIME type of scripts loaded by importScripts(). r=dveditz
☠☠ backed out by 015cdc788e05 ☠ ☠
authorTom Schuster <evilpies@gmail.com>
Tue, 29 Jan 2019 16:44:58 +0000
changeset 455966 d085f7afb20a6718b42e4735c269a1b81f2c0065
parent 455965 de20609039acd48d5cc50932d4355a7679af96ae
child 455967 a1ff781d6669b5732a595cb878bf4434e6758b3d
push id35465
push usershindli@mozilla.com
push dateWed, 30 Jan 2019 04:10:12 +0000
treeherdermozilla-central@9e919be867b3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdveditz
bugs1514680
milestone67.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 1514680 - Strictly enforce the MIME type of scripts loaded by importScripts(). r=dveditz Differential Revision: https://phabricator.services.mozilla.com/D16730
devtools/client/webconsole/test/mochitest/browser.ini
devtools/client/webconsole/test/mochitest/browser_webconsole_non_javascript_mime_worker_error.js
devtools/client/webconsole/test/mochitest/test-non-javascript-mime-worker.html
dom/locales/en-US/chrome/security/security.properties
modules/libpref/init/all.js
netwerk/protocol/http/nsHttpChannel.cpp
--- a/devtools/client/webconsole/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/test/mochitest/browser.ini
@@ -132,16 +132,17 @@ support-files =
   test-mixedcontent-securityerrors.html
   test-mutation.html
   test-network-exceptions.html
   test-network-request.html
   test-network.html
   test-non-javascript-mime.html
   test-non-javascript-mime.js
   test-non-javascript-mime.js^headers^
+  test-non-javascript-mime-worker.html
   test-observe-http-ajax.html
   test-own-console.html
   test-property-provider.html
   test-reopen-closed-tab.html
   test-result-format-as-string.html
   test-sourcemap-error-01.html
   test-sourcemap-error-01.js
   test-sourcemap-error-02.html
@@ -351,16 +352,17 @@ skip-if = true #	Bug 1404382
 skip-if = true  # Bug 1438979
 [browser_webconsole_network_messages_openinnet.js]
 [browser_webconsole_network_messages_status_code.js]
 [browser_webconsole_network_requests_from_chrome.js]
 [browser_webconsole_network_reset_filter.js]
 [browser_webconsole_nodes_highlight.js]
 [browser_webconsole_nodes_select.js]
 [browser_webconsole_non_javascript_mime_warning.js]
+[browser_webconsole_non_javascript_mime_worker_error.js]
 [browser_webconsole_object_ctrl_click.js]
 [browser_webconsole_object_in_sidebar_keyboard_nav.js]
 [browser_webconsole_object_inspector.js]
 [browser_webconsole_object_inspector__proto__.js]
 [browser_webconsole_object_inspector_entries.js]
 [browser_webconsole_object_inspector_getters.js]
 [browser_webconsole_object_inspector_getters_prototype.js]
 [browser_webconsole_object_inspector_getters_shadowed.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_non_javascript_mime_worker_error.js
@@ -0,0 +1,21 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that importScripts loads inside a worker with a non-JavaScript
+// MIME types produce an error and fail.
+// See Bug 1514680.
+
+"use strict";
+
+const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
+                 "test/mochitest/" +
+                 "test-non-javascript-mime-worker.html";
+const MIME_ERROR_MSG = "Loading script from “http://example.com/browser/devtools/client/webconsole/test/mochitest/test-non-javascript-mime.js” with importScripts() was blocked because of a disallowed MIME type (“text/plain”).";
+
+add_task(async function() {
+  const hud = await openNewTabAndConsole(TEST_URI);
+  await waitFor(()=> findMessage(hud, MIME_ERROR_MSG, ".message.error"), "", 100);
+  ok(true, "MIME type error displayed");
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/mochitest/test-non-javascript-mime-worker.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <title>Web Console test for script with non-JavaScript MIME type</title>
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+    <script>
+        "use strict";
+        const source = `importScripts("http://example.com/browser/devtools/client/webconsole/" +
+                                      "test/mochitest/" +
+                                      "test-non-javascript-mime.js");`;
+        const url = URL.createObjectURL(new Blob([source], {type: "application/javascript"}));
+        new Worker(url);
+    </script>
+  </head>
+  <body>
+    <p>Web Console test for importScripts() inside Worker with non-JavaScript MIME type.</p>
+  </body>
+</html>
--- a/dom/locales/en-US/chrome/security/security.properties
+++ b/dom/locales/en-US/chrome/security/security.properties
@@ -81,16 +81,18 @@ WeakCipherSuiteWarning=This site uses th
 #XCTO: nosniff
 # LOCALIZATION NOTE: Do not translate "X-Content-Type-Options: nosniff".
 MimeTypeMismatch2=The resource from “%1$S” was blocked due to MIME type (“%2$S”) mismatch (X-Content-Type-Options: nosniff).
 # LOCALIZATION NOTE: Do not translate "X-Content-Type-Options" and also do not trasnlate "nosniff".
 XCTOHeaderValueMissing=X-Content-Type-Options header warning: value was “%1$S”; did you mean to send “nosniff”?
 
 BlockScriptWithWrongMimeType2=Script from “%1$S” was blocked because of a disallowed MIME type (“%2$S”).
 WarnScriptWithWrongMimeType=The script from “%1$S” was loaded even though its MIME type (“%2$S”) is not a valid JavaScript MIME type.
+# LOCALIZATION NOTE: Do not translate "importScripts()"
+BlockImportScriptsWithWrongMimeType=Loading script from “%1$S” with importScripts() was blocked because of a disallowed MIME type (“%2$S”).
 
 # LOCALIZATION NOTE: Do not translate "data: URI".
 BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”)
 BlockSubresourceRedirectToData=Redirecting to insecure data: URI not allowed (Blocked loading of: “%1$S”)
 
 BlockSubresourceFTP=Loading FTP subresource within http(s) page not allowed (Blocked loading of: “%1$S”)
 
 # LOCALIZATION NOTE (BrowserUpgradeInsecureDisplayRequest):
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2700,16 +2700,19 @@ pref("security.mixed_content.upgrade_dis
 pref("security.mixed_content.block_object_subrequest", false);
 
 // Sub-resource integrity
 pref("security.sri.enable", true);
 
 // Block scripts with wrong MIME type such as image/ or video/.
 pref("security.block_script_with_wrong_mime", true);
 
+// Block scripts with wrong MIME type when loading via importScripts() in workers.
+pref("security.block_importScripts_with_wrong_mime", true);
+
 // OCSP must-staple
 pref("security.ssl.enable_ocsp_must_staple", true);
 
 // Insecure Form Field Warning
 pref("security.insecure_field_warning.contextual.enabled", false);
 pref("security.insecure_field_warning.ignore_local_ip_address", true);
 
 // Disable pinning checks by default.
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -1466,89 +1466,95 @@ nsresult EnsureMIMEOfScript(nsHttpChanne
   if (block) {
     // Instead of consulting Preferences::GetBool() all the time we
     // can cache the result to speed things up.
     static bool sCachedBlockScriptWithWrongMime = false;
     static bool sIsInited = false;
     if (!sIsInited) {
       sIsInited = true;
       Preferences::AddBoolVarCache(&sCachedBlockScriptWithWrongMime,
-                                   "security.block_script_with_wrong_mime");
+                                   "security.block_script_with_wrong_mime",
+                                   true);
     }
 
     // Do not block the load if the feature is not enabled.
     if (!sCachedBlockScriptWithWrongMime) {
       return NS_OK;
     }
 
     ReportMimeTypeMismatch(aChannel, "BlockScriptWithWrongMimeType2", aURI,
                            contentType, Report::Error);
     return NS_ERROR_CORRUPTED_CONTENT;
   }
 
   if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/plain"))) {
     // script load has type text/plain
     AccumulateCategorical(
         Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_plain);
-    return NS_OK;
-  }
-
-  if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/xml"))) {
+  } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/xml"))) {
     // script load has type text/xml
     AccumulateCategorical(
         Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_xml);
-    return NS_OK;
-  }
-
-  if (StringBeginsWith(contentType,
-                       NS_LITERAL_CSTRING("application/octet-stream"))) {
+  } else if (StringBeginsWith(contentType,
+                              NS_LITERAL_CSTRING("application/octet-stream"))) {
     // script load has type application/octet-stream
     AccumulateCategorical(
         Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_octet_stream);
-    return NS_OK;
-  }
-
-  if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("application/xml"))) {
+  } else if (StringBeginsWith(contentType,
+                              NS_LITERAL_CSTRING("application/xml"))) {
     // script load has type application/xml
     AccumulateCategorical(
         Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_xml);
-    return NS_OK;
-  }
-
-  if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("application/json"))) {
+  } else if (StringBeginsWith(contentType,
+                              NS_LITERAL_CSTRING("application/json"))) {
     // script load has type application/json
     AccumulateCategorical(
         Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_json);
-    return NS_OK;
-  }
-
-  if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/json"))) {
+  } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/json"))) {
     // script load has type text/json
     AccumulateCategorical(
         Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_json);
-    return NS_OK;
-  }
-
-  if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/html"))) {
+  } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/html"))) {
     // script load has type text/html
     AccumulateCategorical(
         Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_html);
-    return NS_OK;
-  }
-
-  if (contentType.IsEmpty()) {
+  } else if (contentType.IsEmpty()) {
     // script load has no type
     AccumulateCategorical(
         Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::empty);
-    return NS_OK;
-  }
-
-  // script load has unknown type
-  AccumulateCategorical(
-      Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::unknown);
+  } else {
+    // script load has unknown type
+    AccumulateCategorical(
+        Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::unknown);
+  }
+
+  // We restrict importScripts() in worker code to JavaScript MIME types.
+  if (aLoadInfo->InternalContentPolicyType() ==
+      nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS) {
+    // Instead of consulting Preferences::GetBool() all the time we
+    // can cache the result to speed things up.
+    static bool sCachedBlockImportScriptsWithWrongMime = false;
+    static bool sIsInited = false;
+    if (!sIsInited) {
+      sIsInited = true;
+      Preferences::AddBoolVarCache(
+          &sCachedBlockImportScriptsWithWrongMime,
+          "security.block_importScripts_with_wrong_mime", true);
+    }
+
+    // Do not block the load if the feature is not enabled.
+    if (!sCachedBlockImportScriptsWithWrongMime) {
+      return NS_OK;
+    }
+
+    ReportMimeTypeMismatch(aChannel, "BlockImportScriptsWithWrongMimeType",
+                           aURI, contentType, Report::Error);
+    return NS_ERROR_CORRUPTED_CONTENT;
+  }
+
   return NS_OK;
 }
 
 // Warn when a load of type script uses a wrong MIME type and
 // wasn't blocked by EnsureMIMEOfScript or ProcessXCTO.
 void WarnWrongMIMEOfScript(nsHttpChannel *aChannel, nsIURI *aURI,
                            nsHttpResponseHead *aResponseHead,
                            nsILoadInfo *aLoadInfo) {