Moderate firefox Logic Error 🔧 Commit mapped

Overview

Moderate
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionMitigation bypass in the DOM: Security component
ComponentDOM
Bug ClassLogic Error
Tracker1926318
Fix commit8e238cf525b2 (firefox) +46/-50
CISA KEVNot listed
CreditedMirko Brodesser
Disclosed2026-10-13

Files Changed

  • dom/jsurl/nsJSProtocolHandler.cpp
  • netwerk/base/LoadInfo.h
  • netwerk/base/TRRLoadInfo.cpp
  • netwerk/base/nsILoadInfo.idl
  • testing/web-platform/meta/content-security-policy/inheritance/inheritance-from-initiator.sub.html.ini
diff --git a/dom/jsurl/nsJSProtocolHandler.cpp b/dom/jsurl/nsJSProtocolHandler.cpp
index d9e9781a478..23a129179e5 100644
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -337,6 +337,20 @@ nsresult JSURLInputStream::EvaluateScript(
       }
     }
 
+    // https://html.spec.whatwg.org/#evaluate-a-javascript:-url
+    // Step 12. Let policyContainer be targetNavigable's active document's
+    //          policy container.
+    //
+    // A document created from the string this script evaluates to inherits the
+    // target document's policy container, not the initiating document's one
+    // that docshell stored on the loadinfo for the check above. Store an actual
+    // copy so that modifications done by the new document (such as its meta
+    // CSP) don't propagate back into the target document.
+    RefPtr policyContainerToInherit = mozilla::MakeRefPtr<PolicyContainer>();
+    policyContainerToInherit->InitFromOther(
+        PolicyContainer::Cast(targetDoc->GetPolicyContainer()));
+    loadInfo->SetPolicyContainerToInherit(policyContainerToInherit);
+
     // If the original channel's nsILoadInfo has a PermissionsPolicyInfo,
     // copy it to the new channel.
     if (nsCOMPtr<nsIChannel> originalChannel = targetDoc->GetChannel()) {
diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
index c078b935277..a6a44ac715a 100644
--- a/netwerk/base/LoadInfo.h
+++ b/netwerk/base/LoadInfo.h
@@ -344,31 +344,6 @@ class LoadInfo final : public nsILoadInfo {
   dom::ReferrerPolicy GetFrameReferrerPolicySnapshot() const;
   void SetFrameReferrerPolicySnapshot(dom::ReferrerPolicy aPolicy);
 
-  // Hands off from the cspToInherit functionality!
-  //
-  // For navigations, GetCSPToInherit returns what the spec calls the
-  // "request's client's global object's CSP list", or more precisely
-  // a snapshot of it taken when the navigation starts.  For
-  // navigations that need to inherit their CSP, this is the right CSP
-  // to use for the new document.  We need a way to transfer the CSP
-  // from the docshell (where the navigation starts) to the point where
-  // the new document is created and decides whether to inherit its
-  // CSP, and this is the mechanism we use for that.
-  //
-  // For example:
-  // A document with a CSP triggers a new top-level data: URI load.
-  // We pass the CSP of the document that triggered the load all the
-  // way to docshell. Within docshell we call SetCSPToInherit() on the
-  // loadinfo. Within Document::InitCSP() we check if the newly created
-  // document needs to inherit the CSP. If so, we call
-  // GetCSPToInherit() and set the inherited CSP as the CSP for the new
-  // document. Please note that any additonal Meta CSP in that document
-  // will be merged into that CSP. Any subresource loads within that
-  // document subesquently will receive the correct CSP by querying
-  // loadinfo->GetCsp() from that point on.
-  void SetPolicyContainerToInherit(
-      nsIPolicyContainer* aPolicyContainerToInherit);
-
   bool HasIsThirdPartyContextToTopWindowSet() {
     return mIsThirdPartyContextToTopWindow.isSome();
   }
diff --git a/netwerk/base/TRRLoadInfo.cpp b/netwerk/base/TRRLoadInfo.cpp
index 0d8b34cfb93..0cba5455007 100644
--- a/netwerk/base/TRRLoadInfo.cpp
+++ b/netwerk/base/TRRLoadInfo.cpp
@@ -497,6 +497,9 @@ TRRLoadInfo::GetPolicyContainerToInherit() {
   return nullptr;
 }
 
+void TRRLoadInfo::SetPolicyContainerToInherit(
+    nsIPolicyContainer* aPolicyContainerToInherit) {}
+
 Maybe<PermissionsPolicyInfo> TRRLoadInfo::GetContainerPermissionsPolicyInfo() {
   return Nothing();
 }
diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl
index 3279d195d47..a3e7384515b 100644
--- a/netwerk/base/nsILoadInfo.idl
+++ b/netwerk/base/nsILoadInfo.idl
@@ -1474,7 +1474,36 @@ interface nsILoadInfo : nsISupports
   [notxpcom,nostdcall] CSPRef GetPreloadCsp();
 
   [notxpcom,nostdcall] PolicyContainerRef GetPolicyContainer();
+
+  /**
+   * Hands off from the policyContainerToInherit functionality!
+   *
+   * For navigations, GetPolicyContainerToInherit returns what the spec calls
+   * the "request's client's global object's CSP list", or more precisely a
+   * snapshot of it taken when the navigation starts.  For navigations that
+   * need to inherit their CSP, this is the right CSP to use for the new
+   * document.  We need a way to transfer the CSP from the docshell (where the
+   * navigation starts) to the point where the new document is created and
+   * decides whether to inherit its CSP, and this is the mechanism we use for
+   * that.
+   *
+   * For example:
+   * A document with a CSP triggers a new top-level data: URI load.
+   * We pass the CSP of the document that triggered the load all the
+   * way to docshell. Within docshell we call SetPolicyContainerToInherit() on
+   * the loadinfo. Within Document::InitPolicyContainer() we check if the newly
+   * created document needs to inherit the policy container. If so, we call
+   * GetPolicyContainerToInherit(). Please note that any additonal Meta CSP in
+   * that document will be merged into that CSP. Any subresource loads within
+   * that document subesquently will receive the correct CSP by querying
+   * loadinfo->GetPolicyContainer() from that point on.
+   *
+   * javascript: URLs are the exception: the document they create inherits the
+   * policy container of the document it replaces, so nsJSThunk overrides the
+   * value docshell set here once it knows that document.
+   */
   [notxpcom,nostdcall] PolicyContainerRef GetPolicyContainerToInherit();
+  [notxpcom,nostdcall] void SetPolicyContainerToInherit(in nsIPolicyContainer aPolicyContainerToInherit);
 
   /**
     * The possibly cross-origin container permissions policy required to
diff --git a/testing/web-platform/meta/content-security-policy/inheritance/inheritance-from-initiator.sub.html.ini b/testing/web-platform/meta/content-security-policy/inheritance/inheritance-from-initiator.sub.html.ini
index e3e7fd6064b..826273ffe5b 100644
--- a/testing/web-platform/meta/content-security-policy/inheritance/inheritance-from-initiator.sub.html.ini
+++ b/testing/web-platform/meta/content-security-policy/inheritance/inheritance-from-initiator.sub.html.ini
@@ -12,28 +12,3 @@
   [blob: Click on anchor inherits from owner of the anchor (apart from javascript:, which keeps target policies, and blob:, which always inherits from creator).]
     expected: FAIL
 
-
-[inheritance-from-initiator.sub.html?scheme=javascript]
-  [javascript: Setting src inherits from parent (apart from javascript:, which keeps target policies).]
-    expected: FAIL
-
-  [javascript: Changing contentWindow.location inherits from who changed it (apart from javascript:, which keeps target policies, and blob:, which always inherits from creator).]
-    expected: FAIL
-
-  [javascript: Changing contentWindow.location indirectly inherits from who changed it directly (apart from javascript:, which keeps target policies).]
-    expected: FAIL
-
-  [javascript: window.open() inherits from caller (apart from javascript:, which keeps target policies, and blob:, which always inherits from creator).]
-    expected: FAIL
-
-  [javascript: Click on anchor inherits from owner of the anchor (apart from javascript:, which keeps target policies, and blob:, which always inherits from creator).]
-    expected: FAIL
-
-  [javascript: Form submission through submit() inherits  from owner of form (apart from javascript:, which keeps target policies).]
-    expected: FAIL
-
-  [javascript: Form submission through button click inherits from owner of form (apart from javascript:, which keeps target policies).]
-    expected: FAIL
-
-
-[inheritance-from-initiator.sub.html?scheme=data]
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/testing/web-platform/meta/content-security-policy/inheritance/inheritance-from-initiator.sub.html.ini b/testing/web-platform/meta/content-security-policy/inheritance/inheritance-from-initiator.sub.html.ini
index e3e7fd6064b..826273ffe5b 100644
--- a/testing/web-platform/meta/content-security-policy/inheritance/inheritance-from-initiator.sub.html.ini
+++ b/testing/web-platform/meta/content-security-policy/inheritance/inheritance-from-initiator.sub.html.ini
@@ -12,28 +12,3 @@
   [blob: Click on anchor inherits from owner of the anchor (apart from javascript:, which keeps target policies, and blob:, which always inherits from creator).]
     expected: FAIL
 
-
-[inheritance-from-initiator.sub.html?scheme=javascript]
-  [javascript: Setting src inherits from parent (apart from javascript:, which keeps target policies).]
-    expected: FAIL
-
-  [javascript: Changing contentWindow.location inherits from who changed it (apart from javascript:, which keeps target policies, and blob:, which always inherits from creator).]
-    expected: FAIL
-
-  [javascript: Changing contentWindow.location indirectly inherits from who changed it directly (apart from javascript:, which keeps target policies).]
-    expected: FAIL
-
-  [javascript: window.open() inherits from caller (apart from javascript:, which keeps target policies, and blob:, which always inherits from creator).]
-    expected: FAIL
-
-  [javascript: Click on anchor inherits from owner of the anchor (apart from javascript:, which keeps target policies, and blob:, which always inherits from creator).]
-    expected: FAIL
-
-  [javascript: Form submission through submit() inherits  from owner of form (apart from javascript:, which keeps target policies).]
-    expected: FAIL
-
-  [javascript: Form submission through button click inherits from owner of form (apart from javascript:, which keeps target policies).]
-    expected: FAIL
-
-
-[inheritance-from-initiator.sub.html?scheme=data]
Loading diff…