Bug 1560915 - Hardcode minimal eval()-whitelist for test files into eval()-assertion, r=ckerschb
authorJonas Allmann <jallmann@mozilla.com>
Wed, 17 Jul 2019 12:21:29 +0000
changeset 483125 6e76b0cb3e10217eebec87160de66c97a04519ed
parent 483124 54e5c7e82504eef2244f7d34432cf662b820eb23
child 483126 9afcb33144f71e689b8778e27c874265f77b00d5
push id36307
push useraciure@mozilla.com
push dateThu, 18 Jul 2019 03:45:56 +0000
treeherdermozilla-central@3d0e35ab6850 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb
bugs1560915
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 1560915 - Hardcode minimal eval()-whitelist for test files into eval()-assertion, r=ckerschb Differential Revision: https://phabricator.services.mozilla.com/D37695
dom/security/nsContentSecurityManager.cpp
modules/libpref/init/StaticPrefList.h
modules/libpref/init/all.js
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -29,16 +29,45 @@
 #include "mozilla/Logging.h"
 #include "xpcpublic.h"
 
 NS_IMPL_ISUPPORTS(nsContentSecurityManager, nsIContentSecurityManager,
                   nsIChannelEventSink)
 
 static mozilla::LazyLogModule sCSMLog("CSMLog");
 
+// This whitelist contains files that are permanently allowed to use eval()-like
+// functions. It is supposed to be restricted to files that are exclusively used
+// in testing contexts.
+static nsLiteralCString evalWhitelist[] = {
+    // Test-only third-party library
+    NS_LITERAL_CSTRING("resource://testing-common/sinon-7.2.7.js"),
+    // Test-only third-party library
+    NS_LITERAL_CSTRING("resource://testing-common/ajv-4.1.1.js"),
+    // Test-only utility
+    NS_LITERAL_CSTRING("resource://testing-common/content-task.js"),
+
+    // The following files are NOT supposed to stay on this whitelist.
+    // Bug numbers indicate planned removal of each file.
+
+    // Bug 1498560
+    NS_LITERAL_CSTRING("chrome://global/content/bindings/autocomplete.xml"),
+    // Bug 1550485
+    NS_LITERAL_CSTRING("resource://devtools/client/shared/vendor/redux.js"),
+    // Bug 1550489
+    NS_LITERAL_CSTRING(
+        "resource://devtools/client/shared/vendor/react-redux.js"),
+    // Bug 1550463
+    NS_LITERAL_CSTRING("resource://devtools/client/shared/vendor/lodash.js"),
+    // Bug 1550471
+    NS_LITERAL_CSTRING("resource://devtools/client/shared/vendor/jszip.js"),
+    // Bug 1550476
+    NS_LITERAL_CSTRING("resource://devtools/client/shared/vendor/jsol.js"),
+};
+
 /* static */
 bool nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
     nsIChannel* aChannel) {
   // Let's block all toplevel document navigations to a data: URI.
   // In all cases where the toplevel document is navigated to a
   // data: URI the triggeringPrincipal is a contentPrincipal, or
   // a NullPrincipal. In other cases, e.g. typing a data: URL into
   // the URL-Bar, the triggeringPrincipal is a SystemPrincipal;
@@ -162,46 +191,36 @@ bool nsContentSecurityManager::AllowInse
 
 /* static */
 void nsContentSecurityManager::AssertEvalNotUsingSystemPrincipal(
     nsIPrincipal* subjectPrincipal, JSContext* cx) {
   if (!subjectPrincipal->IsSystemPrincipal()) {
     return;
   }
 
-  if (Preferences::GetBool("security.allow_eval_with_system_principal")) {
+  // Use static pref for performance reasons.
+  if (StaticPrefs::security_allow_eval_with_system_principal()) {
     return;
   }
 
-  static StaticAutoPtr<nsTArray<nsCString>> sUrisAllowEval;
   JS::AutoFilename scriptFilename;
   if (JS::DescribeScriptedCaller(cx, &scriptFilename)) {
-    if (!sUrisAllowEval) {
-      sUrisAllowEval = new nsTArray<nsCString>();
-      nsAutoCString urisAllowEval;
-      Preferences::GetCString("security.uris_using_eval_with_system_principal",
-                              urisAllowEval);
-      for (const nsACString& filenameString : urisAllowEval.Split(',')) {
-        sUrisAllowEval->AppendElement(filenameString);
-      }
-      ClearOnShutdown(&sUrisAllowEval);
-    }
+    nsDependentCSubstring fileName(scriptFilename.get(),
+                                   strlen(scriptFilename.get()));
 
-    nsAutoCString fileName;
-    fileName = nsAutoCString(scriptFilename.get());
+    ToLowerCase(fileName);
     // Extract file name alone if scriptFilename contains line number
     // separated by multiple space delimiters in few cases.
     int32_t fileNameIndex = fileName.FindChar(' ');
     if (fileNameIndex != -1) {
-      fileName = Substring(fileName, 0, fileNameIndex);
+      fileName.SetLength(fileNameIndex);
     }
-    ToLowerCase(fileName);
 
-    for (auto& uriEntry : *sUrisAllowEval) {
-      if (StringEndsWith(fileName, uriEntry)) {
+    for (const nsLiteralCString& whitelistEntry : evalWhitelist) {
+      if (fileName.Equals(whitelistEntry)) {
         return;
       }
     }
   }
 
   MOZ_ASSERT(false, "do not use eval with system privileges");
 }
 
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -7401,16 +7401,23 @@ VARCACHE_PREF(
 
 VARCACHE_PREF(
   Live,
   "security.csp.reporting.script-sample.max-length",
   security_csp_reporting_script_sample_max_length,
   int32_t, 40
 )
 
+VARCACHE_PREF(
+  Live,
+  "security.allow_eval_with_system_principal",
+  security_allow_eval_with_system_principal,
+  bool, false
+)
+
 // Whether strict file origin policy is in effect.
 VARCACHE_PREF(
   Live,
   "security.fileuri.strict_origin_policy",
   security_fileuri_strict_origin_policy,
   RelaxedAtomicBool, true
 )
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2445,19 +2445,16 @@ pref("security.directory",              
 pref("security.dialog_enable_delay", 1000);
 pref("security.notification_enable_delay", 500);
 
 #if defined(DEBUG) && !defined(ANDROID)
 pref("csp.about_uris_without_csp", "blank,printpreview,srcdoc,addons,config,downloads,home,newtab,preferences,sync-log");
 // the following prefs are for testing purposes only.
 pref("csp.overrule_about_uris_without_csp_whitelist", false);
 pref("csp.skip_about_page_has_csp_assert", false);
-// assertion flag will be set to false after fixing Bug 1473549
-pref("security.allow_eval_with_system_principal", false);
-pref("security.uris_using_eval_with_system_principal", "autocomplete.xml,redux.js,react-redux.js,content-task.js,lodash.js,jszip.js,sinon-7.2.7.js,ajv-4.1.1.js,jsol.js");
 #endif
 
 #ifdef EARLY_BETA_OR_EARLIER
 // Disallow web documents loaded with the SystemPrincipal
 pref("security.disallow_non_local_systemprincipal_in_tests", false);
 #endif
 
 // Mixed content blocking