High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionSame-origin policy bypass in the CSS Parsing and Computation component
ComponentLayout
Bug ClassLogic Error
Tracker2079209
Fix commitee6eaa5a9b93 (firefox) +53/-17
CISA KEVNot listed
CreditedTakashi Suzuki
Disclosed2026-10-27

Changed Functions

FunctionChangeNotes
if
layout/style/Loader.cpp
modified
mIsLinkRelPreloadOrEarlyHint
layout/style/Loader.h
modified
mSRIMetadata
layout/style/Loader.h
modified

Files Changed

  • layout/style/Loader.cpp
  • layout/style/Loader.h
  • testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet-helper.sub.svg
  • testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet.sub.html
diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp
index 4a1ad784ceb..8574121f538 100644
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -143,7 +143,9 @@ SheetLoadDataHashKey::SheetLoadDataHashKey(const css::SheetLoadData& aLoadData)
       mCORSMode(aLoadData.mSheet->GetCORSMode()),
       mOrigin(aLoadData.mSheet->GetOrigin()),
       mCompatMode(aLoadData.mCompatMode),
-      mIsLinkRelPreloadOrEarlyHint(aLoadData.IsLinkRelPreloadOrEarlyHint()) {
+      mIsLinkRelPreloadOrEarlyHint(aLoadData.IsLinkRelPreloadOrEarlyHint()),
+      mLoadedAsImage(aLoadData.mLoader->GetDocument() &&
+                     aLoadData.mLoader->GetDocument()->IsBeingUsedAsImage()) {
   MOZ_COUNT_CTOR(SheetLoadDataHashKey);
   MOZ_ASSERT(mURI);
   MOZ_ASSERT(mLoaderPrincipal);
@@ -186,6 +188,11 @@ bool SheetLoadDataHashKey::KeyEquals(const SheetLoadDataHashKey& aKey) const {
     return false;
   }
 
+  if (mLoadedAsImage != aKey.mLoadedAsImage) {
+    LOG((" > Loaded as image mismatch\n"));
+    return false;
+  }
+
   // If encoding differs, then don't reuse the cache.
   //
   // TODO(emilio): When the encoding is determined from the request (either
@@ -949,7 +956,8 @@ Loader::CreateSheet(nsIURI* aURI, nsIContent* aLinkingContent,
                              GetFallbackEncoding(*this, aLinkingContent,
                                                  aPreloadOrParentDataEncoding),
                              aCORSMode, aOrigin, CompatMode(aPreloadKind),
-                             sriMetadata, aPreloadKind);
+                             mDocument && mDocument->IsBeingUsedAsImage(),
+                             aPreloadKind, sriMetadata);
     auto cacheResult = mSheets->Lookup(*this, key, aSyncLoad);
     if (cacheResult.mState != CachedSubResourceState::Miss) {
       SheetState sheetState = SheetState::Complete;
diff --git a/layout/style/Loader.h b/layout/style/Loader.h
index 255ed6707cf..22f6d4054f9 100644
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -59,8 +59,9 @@ class SheetLoadDataHashKey : public PLDHashEntryHdr {
         mCORSMode(aKey->mCORSMode),
         mOrigin(aKey->mOrigin),
         mCompatMode(aKey->mCompatMode),
-        mSRIMetadata(aKey->mSRIMetadata),
-        mIsLinkRelPreloadOrEarlyHint(aKey->mIsLinkRelPreloadOrEarlyHint) {
+        mIsLinkRelPreloadOrEarlyHint(aKey->mIsLinkRelPreloadOrEarlyHint),
+        mLoadedAsImage(aKey->mLoadedAsImage),
+        mSRIMetadata(aKey->mSRIMetadata) {
     MOZ_COUNT_CTOR(SheetLoadDataHashKey);
   }
 
@@ -68,9 +69,9 @@ class SheetLoadDataHashKey : public PLDHashEntryHdr {
                        nsIPrincipal* aPartitionPrincipal,
                        NotNull<const Encoding*> aEncodingGuess,
                        CORSMode aCORSMode, StyleOrigin aOrigin,
-                       nsCompatibility aCompatMode,
-                       const dom::SRIMetadata& aSRIMetadata,
-                       css::StylePreloadKind aPreloadKind)
+                       nsCompatibility aCompatMode, bool aLoadedAsImage,
+                       css::StylePreloadKind aPreloadKind,
+                       const dom::SRIMetadata& aSRIMetadata)
       : mURI(aURI),
         mLoaderPrincipal(aLoaderPrincipal),
         mPartitionPrincipal(aPartitionPrincipal),
@@ -78,9 +79,10 @@ class SheetLoadDataHashKey : public PLDHashEntryHdr {
         mCORSMode(aCORSMode),
         mOrigin(aOrigin),
         mCompatMode(aCompatMode),
-        mSRIMetadata(aSRIMetadata),
         mIsLinkRelPreloadOrEarlyHint(
-            css::IsLinkRelPreloadOrEarlyHint(aPreloadKind)) {
+            css::IsLinkRelPreloadOrEarlyHint(aPreloadKind)),
+        mLoadedAsImage(aLoadedAsImage),
+        mSRIMetadata(aSRIMetadata) {
     MOZ_ASSERT(aURI);
     MOZ_ASSERT(aLoaderPrincipal);
     MOZ_COUNT_CTOR(SheetLoadDataHashKey);
@@ -90,13 +92,13 @@ class SheetLoadDataHashKey : public PLDHashEntryHdr {
       : mURI(std::move(toMove.mURI)),
         mLoaderPrincipal(std::move(toMove.mLoaderPrincipal)),
         mPartitionPrincipal(std::move(toMove.mPartitionPrincipal)),
-        mEncodingGuess(std::move(toMove.mEncodingGuess)),
-        mCORSMode(std::move(toMove.mCORSMode)),
-        mOrigin(std::move(toMove.mOrigin)),
-        mCompatMode(std::move(toMove.mCompatMode)),
-        mSRIMetadata(std::move(toMove.mSRIMetadata)),
-        mIsLinkRelPreloadOrEarlyHint(
-            std::move(toMove.mIsLinkRelPreloadOrEarlyHint)) {
+        mEncodingGuess(toMove.mEncodingGuess),
+        mCORSMode(toMove.mCORSMode),
+        mOrigin(toMove.mOrigin),
+        mCompatMode(toMove.mCompatMode),
+        mIsLinkRelPreloadOrEarlyHint(toMove.mIsLinkRelPreloadOrEarlyHint),
+        mLoadedAsImage(toMove.mLoadedAsImage),
+        mSRIMetadata(std::move(toMove.mSRIMetadata)) {
     MOZ_COUNT_CTOR(SheetLoadDataHashKey);
   }
 
@@ -141,8 +143,9 @@ class SheetLoadDataHashKey : public PLDHashEntryHdr {
   const CORSMode mCORSMode;
   const StyleOrigin mOrigin;
   const nsCompatibility mCompatMode;
-  dom::SRIMetadata mSRIMetadata;
   const bool mIsLinkRelPreloadOrEarlyHint;
+  const bool mLoadedAsImage;
+  dom::SRIMetadata mSRIMetadata;
 };
 
 namespace css {
diff --git a/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet-helper.sub.svg b/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet-helper.sub.svg
new file mode 100644
index 00000000000..f905c873194
--- /dev/null
+++ b/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet-helper.sub.svg
@@ -0,0 +1,2 @@
+<?xml-stylesheet href="data:text/css,svg{background-image:url(http://{{domains[www1]}}:{{ports[http][0]}}/images/red.png);background-size:100px 100px}"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"></svg>
diff --git a/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet.sub.html b/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet.sub.html
new file mode 100644
index 00000000000..2c16896cbdb
--- /dev/null
+++ b/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet.sub.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>SVG as image doesn't load cross-origin resources from a cached data: URL sheet</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=2079209">
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="author" href="https://mozilla.com" title="Mozilla">
+<link rel="match" href="/svg/struct/reftests/reference/green-100x100.html">
+<link rel="stylesheet" href="data:text/css,svg{background-image:url(http://{{domains[www1]}}:{{ports[http][0]}}/images/red.png);background-size:100px 100px}">
+<svg width="100" height="100" style="position: absolute; left: -1000px"></svg>
+<img width="100" height="100" style="background-color: green">
+<script>
+  window.addEventListener("load", () => {
+    const img = document.querySelector("img");
+    img.onload = img.onerror = () => {
+      requestAnimationFrame(() => requestAnimationFrame(() => {
+        document.documentElement.classList.remove("reftest-wait");
+      }));
+    };
+    img.src = "external-resource-data-url-sheet-helper.sub.svg";
+  });
+</script>
+</html>
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet-helper.sub.svg b/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet-helper.sub.svg
new file mode 100644
index 00000000000..f905c873194
--- /dev/null
+++ b/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet-helper.sub.svg
@@ -0,0 +1,2 @@
+<?xml-stylesheet href="data:text/css,svg{background-image:url(http://{{domains[www1]}}:{{ports[http][0]}}/images/red.png);background-size:100px 100px}"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"></svg>
diff --git a/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet.sub.html b/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet.sub.html
new file mode 100644
index 00000000000..2c16896cbdb
--- /dev/null
+++ b/testing/web-platform/tests/svg/as-image/external-resource-data-url-sheet.sub.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>SVG as image doesn't load cross-origin resources from a cached data: URL sheet</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=2079209">
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="author" href="https://mozilla.com" title="Mozilla">
+<link rel="match" href="/svg/struct/reftests/reference/green-100x100.html">
+<link rel="stylesheet" href="data:text/css,svg{background-image:url(http://{{domains[www1]}}:{{ports[http][0]}}/images/red.png);background-size:100px 100px}">
+<svg width="100" height="100" style="position: absolute; left: -1000px"></svg>
+<img width="100" height="100" style="background-color: green">
+<script>
+  window.addEventListener("load", () => {
+    const img = document.querySelector("img");
+    img.onload = img.onerror = () => {
+      requestAnimationFrame(() => requestAnimationFrame(() => {
+        document.documentElement.classList.remove("reftest-wait");
+      }));
+    };
+    img.src = "external-resource-data-url-sheet-helper.sub.svg";
+  });
+</script>
+</html>
Loading diff…