High firefox Cross Origin 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionA compromised content process could have allowed for the arbitrary loading of cross-origin pages.
ComponentDOM
Bug ClassCross Origin
Tracker1905843
Fix commit95ef09ee461a (firefox) +67/-2
CISA KEVNot listed
CreditedJan Drescher and David Klein from IAS, TU Braunschweig
Disclosed2024-10-01

Files Changed

  • caps/nsScriptSecurityManager.h
  • dom/security/nsContentSecurityManager.cpp
  • dom/security/nsContentSecurityManager.h
diff --git a/caps/nsScriptSecurityManager.h b/caps/nsScriptSecurityManager.h
index f97170b145e..5400c9f2254 100644
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -81,8 +81,6 @@ class nsScriptSecurityManager final : public nsIScriptSecurityManager {
                               bool aFromPrivateWindow,
                               uint64_t aInnerWindowID = 0);
 
-  static uint32_t HashPrincipalByOrigin(nsIPrincipal* aPrincipal);
-
   static bool GetStrictFileOriginPolicy() { return sStrictFileOriginPolicy; }
 
   void DeactivateDomainPolicy();
diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp
index 9181de82657..7ba51b28667 100644
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -1427,6 +1427,9 @@ nsresult nsContentSecurityManager::doContentSecurityCheck(
   rv = CheckAllowLoadByTriggeringRemoteType(aChannel);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  rv = CheckForIncoherentResultPrincipal(aChannel);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   // if dealing with a redirected channel then we have already installed
   // streamlistener and redirect proxies and so we are done.
   if (loadInfo->GetInitialSecurityCheckDone()) {
@@ -1709,3 +1712,66 @@ nsContentSecurityManager::PerformSecurityCheck(
   inAndOutListener.forget(outStreamListener);
   return NS_OK;
 }
+
+nsresult nsContentSecurityManager::CheckForIncoherentResultPrincipal(
+    nsIChannel* aChannel) {
+  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
+  ExtContentPolicyType contentPolicyType =
+      loadInfo->GetExternalContentPolicyType();
+  if (contentPolicyType != ExtContentPolicyType::TYPE_DOCUMENT &&
+      contentPolicyType != ExtContentPolicyType::TYPE_SUBDOCUMENT &&
+      contentPolicyType != ExtContentPolicyType::TYPE_OBJECT) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIPrincipal> resultOrPrecursor;
+  nsresult rv = nsScriptSecurityManager::GetScriptSecurityManager()
+                    ->GetChannelResultPrincipalIfNotSandboxed(
+                        aChannel, getter_AddRefs(resultOrPrecursor));
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_STATE(resultOrPrecursor);
+
+  if (nsCOMPtr<nsIPrincipal> precursor =
+          resultOrPrecursor->GetPrecursorPrincipal()) {
+    resultOrPrecursor = precursor;
+  }
+
+  if (!resultOrPrecursor->GetIsContentPrincipal()) {
+    return NS_OK;
+  }
+
+  nsAutoCString resultSiteOriginNoSuffix;
+  rv = resultOrPrecursor->GetSiteOriginNoSuffix(resultSiteOriginNoSuffix);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIURI> resultSiteOriginURI;
+  NS_NewURI(getter_AddRefs(resultSiteOriginURI), resultSiteOriginNoSuffix);
+  NS_ENSURE_STATE(resultSiteOriginURI);
+
+  nsCOMPtr<nsIURI> channelURI;
+  aChannel->GetURI(getter_AddRefs(channelURI));
+  NS_ENSURE_STATE(channelURI);
+
+  nsCOMPtr<nsIPrincipal> channelUriPrincipal =
+      BasePrincipal::CreateContentPrincipal(channelURI, {});
+  NS_ENSURE_STATE(channelUriPrincipal);
+
+  nsAutoCString channelUriSiteOrigin;
+  rv = channelUriPrincipal->GetSiteOriginNoSuffix(channelUriSiteOrigin);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIURI> channelSiteOriginURI;
+  NS_NewURI(getter_AddRefs(channelSiteOriginURI), channelUriSiteOrigin);
+  NS_ENSURE_STATE(channelSiteOriginURI);
+
+  if (nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(
+          resultSiteOriginURI, channelSiteOriginURI) ||
+      (!net::SchemeIsHTTP(resultSiteOriginURI) &&
+       !net::SchemeIsHTTPS(resultSiteOriginURI) &&
+       (net::SchemeIsHTTP(channelSiteOriginURI) ||
+        net::SchemeIsHTTPS(channelSiteOriginURI)))) {
+    return NS_ERROR_CONTENT_BLOCKED;
+  }
+
+  return NS_OK;
+}
diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h
index 17d42e9676f..45757a973c1 100644
--- a/dom/security/nsContentSecurityManager.h
+++ b/dom/security/nsContentSecurityManager.h
@@ -87,6 +87,7 @@ class nsContentSecurityManager : public nsIContentSecurityManager,
   static nsresult CheckAllowLoadInPrivilegedAboutContext(nsIChannel* aChannel);
   static nsresult CheckChannelHasProtocolSecurityFlag(nsIChannel* aChannel);
   static bool CrossOriginEmbedderPolicyAllowsCredentials(nsIChannel* aChannel);
+  static nsresult CheckForIncoherentResultPrincipal(nsIChannel* aChannel);
 
   virtual ~nsContentSecurityManager() = default;
 };
Loading diff…