Medium firefox Logic Error 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionAn attacker was able to bypass the <code>connect-src</code> directive of a Content Security Policy by manipulating subdocuments. This would have also hidden the connections from the Network tab in Devtools.
ComponentNetworking
Bug ClassLogic Error
Tracker1966927
Fix commitdd683d9a9a0c (firefox) +52/-2
CISA KEVNot listed
CreditedAlan Li (lebr0nli)
Disclosed2025-06-24

Changed Functions

FunctionChangeNotes
if
netwerk/base/LoadInfo.cpp
modified

Files Changed

  • netwerk/base/LoadInfo.cpp
  • netwerk/base/LoadInfo.h
diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
index 9ebaaf90a79..c9d6cace8de 100644
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -84,9 +84,57 @@ static nsContentPolicyType InternalContentPolicyTypeForFrame(
     const Maybe<mozilla::dom::ClientInfo>& aLoadingClientInfo,
     const Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController,
     uint32_t aSandboxFlags) {
-  return MakeAndAddRef<LoadInfo>(
+  RefPtr<LoadInfo> loadInfo(new LoadInfo(
       aLoadingPrincipal, aTriggeringPrincipal, aLoadingContext, aSecurityFlags,
-      aContentPolicyType, aLoadingClientInfo, aController, aSandboxFlags);
+      aContentPolicyType, aLoadingClientInfo, aController, aSandboxFlags));
+  if (loadInfo->IsDocumentMissingClientInfo()) {
+    return Err(NS_ERROR_CONTENT_BLOCKED);
+  }
+  return loadInfo.forget();
+}
+
+bool LoadInfo::IsDocumentMissingClientInfo() {
+  // Only check in the content process for now.
+  if (!XRE_IsContentProcess() || mClientInfo.isSome()) {
+    return false;
+  }
+
+  // No node means no document, so there is nothing to check.
+  nsCOMPtr<nsINode> node = LoadingNode();
+  if (!node) {
+    return false;
+  }
+
+  // Don't bother checking loads that will end up in a privileged context (for
+  // now).
+  if (mLoadingPrincipal->IsSystemPrincipal()) {
+    return false;
+  }
+  if (mLoadingPrincipal->SchemeIs("about") &&
+      !mLoadingPrincipal->IsContentAccessibleAboutURI()) {
+    return false;
+  }
+
+  // The nsDataDocumentContentPolicy is responsible restricting these documents.
+  Document* doc = node->OwnerDoc();
+  if (doc->IsLoadedAsData() || doc->IsResourceDoc()) {
+    return false;
+  }
+
+  ExtContentPolicy externalType = nsILoadInfo::GetExternalContentPolicyType();
+  if (externalType == ExtContentPolicy::TYPE_DTD ||
+      externalType == ExtContentPolicy::TYPE_OTHER ||
+      externalType == ExtContentPolicy::TYPE_SPECULATIVE ||
+      externalType == ExtContentPolicy::TYPE_SAVEAS_DOWNLOAD ||
+      externalType == ExtContentPolicy::TYPE_DOCUMENT ||
+      externalType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
+    return false;
+  }
+
+  NS_WARNING(
+      "Prevented the creation of a LoadInfo for a document without a "
+      "ClientInfo!");
+  return true;
 }
 
 /* static */ already_AddRefed<LoadInfo> LoadInfo::CreateForDocument(
diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
index 76701d49523..7946dacf862 100644
--- a/netwerk/base/LoadInfo.h
+++ b/netwerk/base/LoadInfo.h
@@ -295,6 +295,8 @@ class LoadInfo final : public nsILoadInfo {
   void ComputeIsThirdPartyContext(nsPIDOMWindowOuter* aOuterWindow);
   void ComputeIsThirdPartyContext(dom::WindowGlobalParent* aGlobal);
 
+  bool IsDocumentMissingClientInfo();
+
   // This function is the *only* function which can change the securityflags
   // of a loadinfo. It only exists because of the XHR code. Don't call it
   // from anywhere else!
Loading diff…