Bug 1226909 part 1: Do security checks in a redirect handler rather than when opening the redirected channel. r=ckerschb
authorJonas Sicking <jonas@sicking.cc>
Sun, 06 Dec 2015 18:33:14 -0500 (2015-12-06)
changeset 275834 e772b5154e0cc25c61307f812d5185296430a07e
parent 275833 0aa2be7bf89908f74cf1aeaf417e55775857ea34
child 275835 dd7c08e6c57236263743eca64d2a1578eccbe569
push id29768
push usercbook@mozilla.com
push dateMon, 07 Dec 2015 13:16:29 +0000 (2015-12-07)
treeherdermozilla-central@59bc3c7a83de [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb
bugs1226909
milestone45.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 1226909 part 1: Do security checks in a redirect handler rather than when opening the redirected channel. r=ckerschb
caps/nsScriptSecurityManager.cpp
caps/nsScriptSecurityManager.h
dom/security/nsContentSecurityManager.cpp
dom/security/nsContentSecurityManager.h
dom/security/test/csp/file_redirects_main.html
dom/security/test/csp/file_redirects_page.sjs
dom/security/test/csp/file_redirects_resource.sjs
dom/security/test/csp/test_redirects.html
layout/build/nsLayoutModule.cpp
netwerk/base/nsIOService.cpp
netwerk/build/nsNetCID.h
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -426,17 +426,16 @@ nsScriptSecurityManager::IsSystemPrincip
 // nsScriptSecurityManager //
 /////////////////////////////
 
 ////////////////////////////////////
 // Methods implementing ISupports //
 ////////////////////////////////////
 NS_IMPL_ISUPPORTS(nsScriptSecurityManager,
                   nsIScriptSecurityManager,
-                  nsIChannelEventSink,
                   nsIObserver)
 
 ///////////////////////////////////////////////////
 // Methods implementing nsIScriptSecurityManager //
 ///////////////////////////////////////////////////
 
 ///////////////// Security Checks /////////////////
 
@@ -1231,51 +1230,16 @@ nsScriptSecurityManager::CanGetService(J
     nsAutoCString errorMsg("Permission denied to get service. CID=");
     char cidStr[NSID_LENGTH];
     aCID.ToProvidedString(cidStr);
     errorMsg.Append(cidStr);
     SetPendingException(cx, errorMsg.get());
     return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
 }
 
-/////////////////////////////////////////////
-// Method implementing nsIChannelEventSink //
-/////////////////////////////////////////////
-NS_IMETHODIMP
-nsScriptSecurityManager::AsyncOnChannelRedirect(nsIChannel* oldChannel, 
-                                                nsIChannel* newChannel,
-                                                uint32_t redirFlags,
-                                                nsIAsyncVerifyRedirectCallback *cb)
-{
-    nsCOMPtr<nsIPrincipal> oldPrincipal;
-    GetChannelResultPrincipal(oldChannel, getter_AddRefs(oldPrincipal));
-
-    nsCOMPtr<nsIURI> newURI;
-    newChannel->GetURI(getter_AddRefs(newURI));
-    nsCOMPtr<nsIURI> newOriginalURI;
-    newChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
-
-    NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
-
-    const uint32_t flags =
-        nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
-        nsIScriptSecurityManager::DISALLOW_SCRIPT;
-    nsresult rv = CheckLoadURIWithPrincipal(oldPrincipal, newURI, flags);
-    if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
-        rv = CheckLoadURIWithPrincipal(oldPrincipal, newOriginalURI, flags);
-    }
-
-    if (NS_FAILED(rv))
-        return rv;
-
-    cb->OnRedirectVerifyCallback(NS_OK);
-    return NS_OK;
-}
-
-
 /////////////////////////////////////
 // Method implementing nsIObserver //
 /////////////////////////////////////
 const char sJSEnabledPrefName[] = "javascript.enabled";
 const char sFileOriginPolicyPrefName[] =
     "security.fileuri.strict_origin_policy";
 
 static const char* kObservedPrefs[] = {
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -9,17 +9,16 @@
 
 #include "nsIScriptSecurityManager.h"
 
 #include "nsIAddonPolicyService.h"
 #include "mozilla/Maybe.h"
 #include "nsIAddonPolicyService.h"
 #include "nsIPrincipal.h"
 #include "nsCOMPtr.h"
-#include "nsIChannelEventSink.h"
 #include "nsIObserver.h"
 #include "nsServiceManagerUtils.h"
 #include "plstr.h"
 #include "js/TypeDecls.h"
 
 #include <stdint.h>
 
 class nsCString;
@@ -34,27 +33,25 @@ class PrincipalOriginAttributes;
 /////////////////////////////
 // nsScriptSecurityManager //
 /////////////////////////////
 #define NS_SCRIPTSECURITYMANAGER_CID \
 { 0x7ee2a4c0, 0x4b93, 0x17d3, \
 { 0xba, 0x18, 0x00, 0x60, 0xb0, 0xf1, 0x99, 0xa2 }}
 
 class nsScriptSecurityManager final : public nsIScriptSecurityManager,
-                                      public nsIChannelEventSink,
                                       public nsIObserver
 {
 public:
     static void Shutdown();
 
     NS_DEFINE_STATIC_CID_ACCESSOR(NS_SCRIPTSECURITYMANAGER_CID)
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISCRIPTSECURITYMANAGER
-    NS_DECL_NSICHANNELEVENTSINK
     NS_DECL_NSIOBSERVER
 
     static nsScriptSecurityManager*
     GetScriptSecurityManager();
 
     // Invoked exactly once, by XPConnect.
     static void InitStatics();
 
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -3,17 +3,19 @@
 #include "nsIStreamListener.h"
 #include "nsILoadInfo.h"
 #include "nsContentUtils.h"
 #include "nsCORSListenerProxy.h"
 #include "nsIStreamListener.h"
 
 #include "mozilla/dom/Element.h"
 
-NS_IMPL_ISUPPORTS(nsContentSecurityManager, nsIContentSecurityManager)
+NS_IMPL_ISUPPORTS(nsContentSecurityManager,
+                  nsIContentSecurityManager,
+                  nsIChannelEventSink)
 
 static nsresult
 ValidateSecurityFlags(nsILoadInfo* aLoadInfo)
 {
   nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
 
   if (securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS &&
       securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED &&
@@ -337,83 +339,145 @@ nsContentSecurityManager::doContentSecur
   NS_ENSURE_ARG(aChannel);
   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
 
   if (!loadInfo) {
     MOZ_ASSERT(false, "channel needs to have loadInfo to perform security checks");
     return NS_ERROR_UNEXPECTED;
   }
 
+  // if dealing with a redirected channel then we have already installed
+  // streamlistener and redirect proxies and so we are done.
+  if (loadInfo->GetInitialSecurityCheckDone()) {
+    return NS_OK;
+  }
+
   // make sure that only one of the five security flags is set in the loadinfo
   // e.g. do not require same origin and allow cross origin at the same time
   nsresult rv = ValidateSecurityFlags(loadInfo);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // lets store the initialSecurityCheckDone flag which indicates whether the channel
-  // was initialy evaluated by the contentSecurityManager. Once the inital
-  // asyncOpen() of the channel went through the contentSecurityManager then
-  // redirects do not have perform all the security checks, e.g. no reason
-  // to setup CORS again.
-  bool initialSecurityCheckDone = loadInfo->GetInitialSecurityCheckDone();
-
-  // now lets set the initalSecurityFlag for subsequent calls
-  rv = loadInfo->SetInitialSecurityCheckDone(true);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   // since aChannel was openend using asyncOpen2() we have to make sure
   // that redirects of that channel also get openend using asyncOpen2()
   // please note that some implementations of ::AsyncOpen2 might already
   // have set that flag to true (e.g. nsViewSourceChannel) in which case
   // we just set the flag again.
   rv = loadInfo->SetEnforceSecurity(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  if (loadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
+    rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  else {
+    rv = CheckChannel(aChannel);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
   nsCOMPtr<nsIURI> finalChannelURI;
   rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalChannelURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Perform all ContentPolicy checks (MixedContent, CSP, ...)
+  rv = DoContentSecurityChecks(finalChannelURI, loadInfo);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // now lets set the initalSecurityFlag for subsequent calls
+  rv = loadInfo->SetInitialSecurityCheckDone(true);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // all security checks passed - lets allow the load
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
+                                                 nsIChannel* aNewChannel,
+                                                 uint32_t aRedirFlags,
+                                                 nsIAsyncVerifyRedirectCallback *aCb)
+{
+  nsCOMPtr<nsILoadInfo> loadInfo = aOldChannel->GetLoadInfo();
+  // Are we enforcing security using LoadInfo?
+  if (loadInfo && loadInfo->GetEnforceSecurity()) {
+    nsresult rv = CheckChannel(aNewChannel);
+    if (NS_FAILED(rv)) {
+      aOldChannel->Cancel(rv);
+      return rv;
+    }
+  }
+
+  // Also verify that the redirecting server is allowed to redirect to the
+  // given URI
+  nsCOMPtr<nsIPrincipal> oldPrincipal;
+  nsContentUtils::GetSecurityManager()->
+    GetChannelResultPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
+
+  nsCOMPtr<nsIURI> newURI;
+  aNewChannel->GetURI(getter_AddRefs(newURI));
+  nsCOMPtr<nsIURI> newOriginalURI;
+  aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
+
+  NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
+
+  const uint32_t flags =
+      nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
+      nsIScriptSecurityManager::DISALLOW_SCRIPT;
+  nsresult rv = nsContentUtils::GetSecurityManager()->
+    CheckLoadURIWithPrincipal(oldPrincipal, newURI, flags);
+  if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
+      rv = nsContentUtils::GetSecurityManager()->
+        CheckLoadURIWithPrincipal(oldPrincipal, newOriginalURI, flags);
+  }
+  NS_ENSURE_SUCCESS(rv, rv);  
+
+  aCb->OnRedirectVerifyCallback(NS_OK);
+  return NS_OK;
+}
+
+/*
+ * Check that this channel passes all security checks. Returns an error code
+ * if this requesst should not be permitted.
+ */
+nsresult
+nsContentSecurityManager::CheckChannel(nsIChannel* aChannel)
+{
+  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
+  MOZ_ASSERT(loadInfo);
+
+  // CORS mode is handled by nsCORSListenerProxy
   nsSecurityFlags securityMode = loadInfo->GetSecurityMode();
+  if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
+  NS_ENSURE_SUCCESS(rv, rv);
+
 
   // if none of the REQUIRE_SAME_ORIGIN flags are set, then SOP does not apply
   if ((securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS) ||
       (securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED)) {
-    rv = DoSOPChecks(finalChannelURI, loadInfo);
+    rv = DoSOPChecks(uri, loadInfo);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  // if dealing with a redirected channel then we only enforce SOP
-  // and can return at this point.
-  if (initialSecurityCheckDone) {
-    return NS_OK;
-  }
-
   if ((securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS) ||
       (securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL)) {
     // Please note that DoCheckLoadURIChecks should only be enforced for
     // cross origin requests. If the flag SEC_REQUIRE_CORS_DATA_INHERITS is set
     // within the loadInfo, then then CheckLoadURIWithPrincipal is performed
     // within nsCorsListenerProxy
-    rv = DoCheckLoadURIChecks(finalChannelURI, loadInfo);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
-    rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener);
+    rv = DoCheckLoadURIChecks(uri, loadInfo);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  // Perform all ContentPolicy checks (MixedContent, CSP, ...)
-  rv = DoContentSecurityChecks(finalChannelURI, loadInfo);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // all security checks passed - lets allow the load
   return NS_OK;
 }
 
-
 // ==== nsIContentSecurityManager implementation =====
 
 NS_IMETHODIMP
 nsContentSecurityManager::PerformSecurityCheck(nsIChannel* aChannel,
                                                nsIStreamListener* aStreamListener,
                                                nsIStreamListener** outStreamListener)
 {
   nsCOMPtr<nsIStreamListener> inAndOutListener = aStreamListener;
--- a/dom/security/nsContentSecurityManager.h
+++ b/dom/security/nsContentSecurityManager.h
@@ -4,34 +4,39 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsContentSecurityManager_h___
 #define nsContentSecurityManager_h___
 
 #include "nsIContentSecurityManager.h"
 #include "nsIChannel.h"
+#include "nsIChannelEventSink.h"
 
 class nsIStreamListener;
 
 #define NS_CONTENTSECURITYMANAGER_CONTRACTID "@mozilla.org/contentsecuritymanager;1"
 // cdcc1ab8-3cea-4e6c-a294-a651fa35227f
 #define NS_CONTENTSECURITYMANAGER_CID \
 { 0xcdcc1ab8, 0x3cea, 0x4e6c, \
   { 0xa2, 0x94, 0xa6, 0x51, 0xfa, 0x35, 0x22, 0x7f } }
 
 class nsContentSecurityManager : public nsIContentSecurityManager
+                               , public nsIChannelEventSink
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTSECURITYMANAGER
+  NS_DECL_NSICHANNELEVENTSINK
 
   nsContentSecurityManager() {}
 
   static nsresult doContentSecurityCheck(nsIChannel* aChannel,
                                          nsCOMPtr<nsIStreamListener>& aInAndOutListener);
 
 private:
+  static nsresult CheckChannel(nsIChannel* aChannel);
+
   virtual ~nsContentSecurityManager() {}
 
 };
 
 #endif /* nsContentSecurityManager_h___ */
--- a/dom/security/test/csp/file_redirects_main.html
+++ b/dom/security/test/csp/file_redirects_main.html
@@ -13,17 +13,16 @@ var page = "/tests/dom/security/test/csp
 
 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 container = document.getElementById("container");
 
--- a/dom/security/test/csp/file_redirects_page.sjs
+++ b/dom/security/test/csp/file_redirects_page.sjs
@@ -9,23 +9,18 @@ function handleRequest(request, response
   });
 
   response.setHeader("Cache-Control", "no-cache", false);
   response.setHeader("Content-Type", "text/html", false);
 
   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'";
-  }
   response.setHeader("Content-Security-Policy",
-      "default-src 'self' blob: ; style-src 'self' 'unsafe-inline'" + additional,
-      false);
+      "default-src 'self' blob: ; style-src 'self' 'unsafe-inline'", false);
 
   // downloadable font that redirects to another site
   if (query["testid"] == "font-src") {
     var resp = '<style type="text/css"> @font-face { font-family:' +
                '"Redirecting Font"; src: url("' + resource +
                '?res=font&redir=other&id=font-src-redir")} #test{font-family:' +
                '"Redirecting Font"}</style></head><body>' +
                '<div id="test">test</div></body>';
@@ -64,22 +59,16 @@ function handleRequest(request, response
   }
 
   // external stylesheet that redirects to another site
   if (query["testid"] == "style-src") {
     response.write('<link rel="stylesheet" type="text/css" href="'+resource+'?res=style&redir=other&id=style-src-redir"></link>');
     return;
   }
 
-  // worker script resource that redirects to another site
-  if (query["testid"] == "worker") {
-    response.write('<script>var worker = new Worker("'+resource+'?res=worker&redir=other&id=worker-redir");</script>');
-    return;
-  }
-
   // script that XHR's to a resource that redirects to another site
   if (query["testid"] == "xhr-src") {
     response.write('<script src="'+resource+'?res=xhr"></script>');
     return;
   }
 
   // for bug949706
   if (query["testid"] == "img-src-from-css") {
--- a/dom/security/test/csp/file_redirects_resource.sjs
+++ b/dom/security/test/csp/file_redirects_resource.sjs
@@ -80,23 +80,16 @@ function handleRequest(request, response
 
   // external stylesheet
   if (query["res"] == "style") {
     response.setHeader("Content-Type", "text/css", false);
     response.write("css data...");
     return;
   }
 
-  // web worker resource
-  if (query["res"] == "worker") {
-    response.setHeader("Content-Type", "application/javascript", false);
-    response.write("worker script data...");
-    return;
-  }
-
   // internal stylesheet that loads an image from an external site
   if (query["res"] == "cssLoader") {
     let bgURL = thisSite + resource + '?redir=other&res=image&id=' + query["id"];
     response.setHeader("Content-Type", "text/css", false);
     response.write("body { background:url('" + bgURL + "'); }");
     return;
   }
 
--- a/dom/security/test/csp/test_redirects.html
+++ b/dom/security/test/csp/test_redirects.html
@@ -77,24 +77,22 @@ var testExpectedResults = { "font-src": 
                             "media-src": true,
                             "media-src-redir": false,
                             "object-src": true,
                             "object-src-redir": false,
                             "script-src": true,
                             "script-src-redir": false,
                             "style-src": true,
                             "style-src-redir": false,
-                            "worker": 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 */
+                            "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,
                           };
 
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -1280,17 +1280,16 @@ static const mozilla::Module::ContractID
   { CSPSERVICE_CONTRACTID, &kCSPSERVICE_CID },
   { NS_CSPCONTEXT_CONTRACTID, &kNS_CSPCONTEXT_CID },
   { NS_MIXEDCONTENTBLOCKER_CONTRACTID, &kNS_MIXEDCONTENTBLOCKER_CID },
   { NS_EVENTLISTENERSERVICE_CONTRACTID, &kNS_EVENTLISTENERSERVICE_CID },
   { NS_GLOBALMESSAGEMANAGER_CONTRACTID, &kNS_GLOBALMESSAGEMANAGER_CID },
   { NS_PARENTPROCESSMESSAGEMANAGER_CONTRACTID, &kNS_PARENTPROCESSMESSAGEMANAGER_CID },
   { NS_CHILDPROCESSMESSAGEMANAGER_CONTRACTID, &kNS_CHILDPROCESSMESSAGEMANAGER_CID },
   { NS_SCRIPTSECURITYMANAGER_CONTRACTID, &kNS_SCRIPTSECURITYMANAGER_CID },
-  { NS_GLOBAL_CHANNELEVENTSINK_CONTRACTID, &kNS_SCRIPTSECURITYMANAGER_CID },
   { NS_PRINCIPAL_CONTRACTID, &kNS_PRINCIPAL_CID },
   { NS_SYSTEMPRINCIPAL_CONTRACTID, &kNS_SYSTEMPRINCIPAL_CID },
   { NS_NULLPRINCIPAL_CONTRACTID, &kNS_NULLPRINCIPAL_CID },
   { NS_DEVICE_SENSORS_CONTRACTID, &kNS_DEVICE_SENSORS_CID },
 #ifndef MOZ_WIDGET_GONK
 #if defined(ANDROID)
   { "@mozilla.org/widget/hapticfeedback;1", &kNS_HAPTICFEEDBACK_CID },
 #endif
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -45,16 +45,17 @@
 #include "mozilla/LoadInfo.h"
 #include "mozilla/net/NeckoCommon.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/net/DNS.h"
 #include "CaptivePortalService.h"
 #include "ClosingService.h"
 #include "ReferrerPolicy.h"
+#include "nsContentSecurityManager.h"
 
 #ifdef MOZ_WIDGET_GONK
 #include "nsINetworkManager.h"
 #include "nsINetworkInterface.h"
 #endif
 
 #if defined(XP_WIN)
 #include "nsNativeConnectionHelper.h"
@@ -410,18 +411,21 @@ nsresult
 nsIOService::AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
                                     uint32_t flags,
                                     nsAsyncRedirectVerifyHelper *helper)
 {
     // If a redirect to a local network address occurs, then chances are we
     // are in a captive portal, so we trigger a recheck.
     RecheckCaptivePortalIfLocalRedirect(newChan);
 
+    // This is silly. I wish there was a simpler way to get at the global
+    // reference of the contentSecurityManager. But it lives in the XPCOM
+    // service registry.
     nsCOMPtr<nsIChannelEventSink> sink =
-        do_GetService(NS_GLOBAL_CHANNELEVENTSINK_CONTRACTID);
+        do_GetService(NS_CONTENTSECURITYMANAGER_CONTRACTID);
     if (sink) {
         nsresult rv = helper->DelegateOnChannelRedirect(sink, oldChan,
                                                         newChan, flags);
         if (NS_FAILED(rv))
             return rv;
     }
 
     // Finally, our category
--- a/netwerk/build/nsNetCID.h
+++ b/netwerk/build/nsNetCID.h
@@ -1000,25 +1000,16 @@
     { 0x86, 0xf8, 0x63, 0xf2, 0x25, 0xb9, 0x40, 0xae } \
   }
 
 /******************************************************************************
  * Contracts that can be implemented by necko users.
  */
 
 /**
- * This contract ID will be gotten as a service and gets the opportunity to look
- * at and veto all redirects that are processed by necko.
- *
- * Must implement nsIChannelEventSink
- */
-#define NS_GLOBAL_CHANNELEVENTSINK_CONTRACTID \
-  "@mozilla.org/netwerk/global-channel-event-sink;1"
-
-/**
  * This contract ID will be gotten as a service implementing nsINetworkLinkService
  * and monitored by IOService for automatic online/offline management.
  *
  * Must implement nsINetworkLinkService
  */
 #define NS_NETWORK_LINK_SERVICE_CONTRACTID \
   "@mozilla.org/network/network-link-service;1"