Low firefox Logic Error 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactlow
DescriptionMemory safety bug fixed in Firefox 152
ComponentDOM
Bug ClassLogic Error
Tracker2007083
Fix commit0e852ba43ace (firefox) +58/-1
CISA KEVNot listed
CreditedFrédéric Wang Nélar
Disclosed2026-06-16

Changed Functions

FunctionChangeNotes
if
dom/mathml/MathMLElement.cpp
modified
if
dom/mathml/MathMLElement.h
modified

Files Changed

  • dom/mathml/MathMLElement.cpp
  • dom/mathml/MathMLElement.h
  • dom/webidl/MathMLElement.webidl
diff --git a/dom/mathml/MathMLElement.cpp b/dom/mathml/MathMLElement.cpp
index 06b11a19d5e..9819d774def 100644
--- a/dom/mathml/MathMLElement.cpp
+++ b/dom/mathml/MathMLElement.cpp
@@ -65,6 +65,20 @@ nsresult MathMLElement::BindToTree(BindContext& aContext, nsINode& aParent) {
 
   Link::BindToTree(aContext);
 
+  // Hide any nonce from the DOM, but keep the internal value of the
+  // nonce by copying and resetting the internal nonce value.
+  if (!aContext.IsMove() && HasFlag(NODE_HAS_NONCE_AND_HEADER_CSP) &&
+      IsInComposedDoc() && OwnerDoc()->GetBrowsingContext()) {
+    nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
+        "MathMLElement::ResetNonce::Runnable",
+        [self = RefPtr<MathMLElement>(this)]() {
+          nsAutoString nonce;
+          self->GetNonce(nonce);
+          self->SetAttr(kNameSpaceID_None, nsGkAtoms::nonce, u""_ns, true);
+          self->SetNonce(nonce);
+        }));
+  }
+
   // Set the bit in the document for telemetry.
   if (Document* doc = aContext.GetComposedDoc()) {
     doc->SetUseCounter(eUseCounter_custom_MathMLUsed);
@@ -642,6 +656,20 @@ nsresult MathMLElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
 
 NS_IMPL_ELEMENT_CLONE(MathMLElement)
 
+nsresult MathMLElement::CopyInnerTo(mozilla::dom::Element* aDest) {
+  nsresult rv = Element::CopyInnerTo(aDest);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  auto* dest = static_cast<MathMLElement*>(aDest);
+
+  // cloning a node must retain its internal nonce slot
+  if (auto* nonce = static_cast<nsString*>(GetProperty(nsGkAtoms::nonce))) {
+    dest->SetNonce(*nonce);
+  }
+
+  return NS_OK;
+}
+
 void MathMLElement::SetIncrementScriptLevel(bool aIncrementScriptLevel,
                                             bool aNotify) {
   NS_ASSERTION(aNotify, "We always notify!");
@@ -757,6 +785,20 @@ void MathMLElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
     }
   }
 
+  // The nonce will be copied over to an internal slot and cleared from the
+  // Element within BindToTree to avoid CSS Selector nonce exfiltration if
+  // the CSP list contains a header-delivered CSP.
+  if (nsGkAtoms::nonce == aName && kNameSpaceID_None == aNameSpaceID) {
+    if (aValue) {
+      SetNonce(nsAttrValueOrString(aValue).String());
+      if (OwnerDoc()->GetHasCSPDeliveredThroughHeader()) {
+        SetFlags(NODE_HAS_NONCE_AND_HEADER_CSP);
+      }
+    } else {
+      RemoveNonce();
+    }
+  }
+
   return MathMLElementBase::AfterSetAttr(aNameSpaceID, aName, aValue, aOldValue,
                                          aSubjectPrincipal, aNotify);
 }
diff --git a/dom/mathml/MathMLElement.h b/dom/mathml/MathMLElement.h
index f8daeb943b2..4b0846796ad 100644
--- a/dom/mathml/MathMLElement.h
+++ b/dom/mathml/MathMLElement.h
@@ -32,6 +32,18 @@ class MathMLElement final : public MathMLElementBase, public Link {
 
   NS_IMPL_FROMNODE(MathMLElement, kNameSpaceID_MathML)
 
+  void SetNonce(const nsAString& aNonce) {
+    SetProperty(nsGkAtoms::nonce, new nsString(aNonce),
+                nsINode::DeleteProperty<nsString>, /* aTransfer = */ true);
+  }
+  void RemoveNonce() { RemoveProperty(nsGkAtoms::nonce); }
+  void GetNonce(nsAString& aNonce) const {
+    nsString* cspNonce = static_cast<nsString*>(GetProperty(nsGkAtoms::nonce));
+    if (cspNonce) {
+      aNonce = *cspNonce;
+    }
+  }
+
   nsresult BindToTree(BindContext&, nsINode& aParent) override;
   void UnbindFromTree(UnbindContext&) override;
 
@@ -66,6 +78,7 @@ class MathMLElement final : public MathMLElementBase, public Link {
   MOZ_CAN_RUN_SCRIPT
   nsresult PostHandleEvent(mozilla::EventChainPostVisitor& aVisitor) override;
   nsresult Clone(mozilla::dom::NodeInfo*, nsINode** aResult) const override;
+  nsresult CopyInnerTo(mozilla::dom::Element* aDest);
 
   // Set during reflow as necessary. Does a style change notification,
   // aNotify must be true.
diff --git a/dom/webidl/MathMLElement.webidl b/dom/webidl/MathMLElement.webidl
index 882a3d1d32a..b51eb392733 100644
--- a/dom/webidl/MathMLElement.webidl
+++ b/dom/webidl/MathMLElement.webidl
@@ -10,7 +10,9 @@
  */
 
 [Exposed=Window]
-interface MathMLElement : Element { };
+interface MathMLElement : Element {
+  attribute DOMString nonce;
+};
 MathMLElement includes GlobalEventHandlers;
 MathMLElement includes HTMLOrSVGOrMathMLElement;
 MathMLElement includes ElementCSSInlineStyle;
Loading diff…