Low chrome Logic Error 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactSide-channel information leakage in SVG
DescriptionSide-channel information leakage in SVG
ComponentSVG
Bug ClassLogic Error
Tracker514406198
Fix commitf7b154b711d7 (chromium/src) +149/-3
CISA KEVNot listed
CreditedGoogle
Disclosed2026-07-29

Changed Functions

FunctionChangeNotes
if
third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc
modified

Files Changed

  • third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc
  • third_party/blink/renderer/platform/runtime_enabled_features.json5
  • third_party/blink/web_tests/external/wpt/css/filter-effects/feImage-orientation.tentative.html
  • third_party/blink/web_tests/external/wpt/css/filter-effects/reference/feImage-orientation-ref.html
From f7b154b711d791f611d5925ac0244eff80bb990f Mon Sep 17 00:00:00 2001
From: Stephen Chenney <schenney@chromium.org>
Date: Thu, 04 Jun 2026 15:30:06 -0700
Subject: [PATCH] Apply EXIF orientation data in SVG feImage filters

Cross-origin images are required to always respect the
image orientation. This was not the case for feImage SVG filter
elements. To address this, always orient images in feImage.

Include a kill switch, as the web compat of this change is unknown.

Bug: 514406198
Change-Id: I7294d8017adc9bed617d78174dada835aa5870dc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7883999
Reviewed-by: Philip Rogers <pdr@chromium.org>
Commit-Queue: Stephen Chenney <schenney@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1641985}
---

diff --git a/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc b/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc
index e90df990..822485f 100644
--- a/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc
+++ b/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc
@@ -170,7 +170,11 @@
     return dest_rect;
   }
   if (scoped_refptr<Image> image = GetImage(dest_rect.size())) {
-    gfx::RectF src_rect(image->SizeAsFloat(kDoNotRespectImageOrientation));
+    RespectImageOrientationEnum orientation = kDoNotRespectImageOrientation;
+    if (RuntimeEnabledFeatures::SvgFeImageEXIFOrientationEnabled()) {
+      orientation = kRespectImageOrientation;
+    }
+    gfx::RectF src_rect(image->SizeAsFloat(orientation));
     preserve_aspect_ratio_->TransformRect(dest_rect, src_rect);
     return dest_rect;
   }
@@ -260,14 +264,33 @@
   scoped_refptr<Image> image = GetImage(dst_rect.size());
   if (PaintImage paint_image =
           image ? image->PaintImageForCurrentFrame() : PaintImage()) {
-    gfx::RectF src_rect(image->SizeAsFloat(kDoNotRespectImageOrientation));
+    RespectImageOrientationEnum orientation = kDoNotRespectImageOrientation;
+    if (RuntimeEnabledFeatures::SvgFeImageEXIFOrientationEnabled()) {
+      orientation = kRespectImageOrientation;
+    }
+    gfx::RectF src_rect(image->SizeAsFloat(orientation));
     preserve_aspect_ratio_->TransformRect(dst_rect, src_rect);
 
     // Adjust the source rectangle if the primitive has been cropped.
     if (crop_rect != dst_rect)
       src_rect = gfx::MapRect(crop_rect, dst_rect, src_rect);
+
+    // Always apply image orientation, because we must for cross-origin images
+    // to respect privacy, and the filter may be applied to multiple elements
+    // with different CSS properties. The filter appearance might then vary
+    // across elements in non-obvious ways.
+    PaintImage oriented_image =
+        orientation == kDoNotRespectImageOrientation
+            ? paint_image
+            : Image::ResizeAndOrientImage(
+                  paint_image,
+                  image ? image->Orientation() : ImageOrientationEnum::kDefault,
+                  gfx::Vector2dF(1, 1), 1, kInterpolationNone, nullptr);
+    if (!oriented_image) {
+      return CreateTransparentBlack();
+    }
     return sk_make_sp<ImagePaintFilter>(
-        std::move(paint_image), gfx::RectFToSkRect(src_rect),
+        std::move(oriented_image), gfx::RectFToSkRect(src_rect),
         gfx::RectFToSkRect(crop_rect), cc::PaintFlags::FilterQuality::kHigh);
   }
   // "A href reference that is an empty image (zero width or zero height),
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index f7ff623..06482ac 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -5813,6 +5813,10 @@
       status: "stable",
     },
     {
+      name: "SvgFeImageEXIFOrientation",
+      status: "stable",
+    },
+    {
       name: "SvgFeImageSkipHiddenContainerViewportDependence",
       status: "stable",
     },
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/feImage-orientation.tentative.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/feImage-orientation.tentative.html
new file mode 100644
index 0000000..f45ecf1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/feImage-orientation.tentative.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Filter Effects: feImage respects EXIF orientation data</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/filter-effects-2/">
+<link rel="match" href="reference/feImage-orientation-ref.html">
+<meta name=fuzzy content="0-5;0-1115">
+</head>
+<body>
+  <svg style="width: 500px; height: 650px">
+    <defs>
+      <filter id="f1" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-1-ul.jpg"/></filter>
+      <filter id="f2" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-2-ur.jpg"/></filter>
+      <filter id="f3" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-3-lr.jpg"/></filter>
+      <filter id="f4" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-4-lol.jpg"/></filter>
+      <filter id="f5" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-5-lu.jpg"/></filter>
+      <filter id="f6" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-6-ru.jpg"/></filter>
+      <filter id="f7" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-7-rl.jpg"/></filter>
+      <filter id="f8" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-8-llo.jpg"/></filter>
+      <filter id="f9" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-9-u.jpg"/></filter>
+    </defs>
+    <rect x="10" y="10" width="100" height="100" filter="url(#f1)"/>
+    <rect x="10" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="00" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="135" y="10" width="100" height="100" filter="url(#f2)" stroke="blue"/>
+    <rect x="135" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="125" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="260" y="10" width="100" height="100" filter="url(#f3)" stroke="blue"/>
+    <rect x="260" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="250" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="10" y="135" width="100" height="100" filter="url(#f4)" stroke="blue"/>
+    <rect x="10" y="135" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="00" y="125" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="135" y="135" width="100" height="100" filter="url(#f5)" stroke="blue"/>
+    <rect x="135" y="135" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="125" y="125" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="260" y="135" width="100" height="100" filter="url(#f6)" stroke="blue"/>
+    <rect x="260" y="135" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="250" y="125" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="10" y="260" width="100" height="100" filter="url(#f7)" stroke="blue"/>
+    <rect x="10" y="260" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="00" y="250" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="135" y="260" width="100" height="100" filter="url(#f6)" stroke="blue"/>
+    <rect x="135" y="260" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="125" y="250" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="260" y="260" width="100" height="100" filter="url(#f8)" stroke="blue"/>
+    <rect x="260" y="260" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="250" y="250" width="120" height="120" fill="none" stroke="green"/>
+  </svg>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/feImage-orientation-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/feImage-orientation-ref.html
new file mode 100644
index 0000000..3a1f6b29
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/feImage-orientation-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Filter Effects: feImage respects EXIF orientation data</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/filter-effects-2/">
+</head>
+<body>
+  <svg style="width: 500px; height: 650px">
+    <defs>
+      <filter id="f1" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-1-ul-pre-rotated.jpg"/></filter>
+      <filter id="f2" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-2-ur-pre-rotated.jpg"/></filter>
+      <filter id="f3" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-3-lr-pre-rotated.jpg"/></filter>
+      <filter id="f4" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-4-lol-pre-rotated.jpg"/></filter>
+      <filter id="f5" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-5-lu-pre-rotated.jpg"/></filter>
+      <filter id="f6" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-6-ru-pre-rotated.jpg"/></filter>
+      <filter id="f7" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-7-rl-pre-rotated.jpg"/></filter>
+      <filter id="f8" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-8-llo-pre-rotated.jpg"/></filter>
+      <filter id="f9" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-9-u-pre-rotated.jpg"/></filter>
+    </defs>
+    <rect x="10" y="10" width="100" height="100" filter="url(#f1)"/>
+    <rect x="10" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="00" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="135" y="10" width="100" height="100" filter="url(#f2)" stroke="blue"/>
+    <rect x="135" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="125" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="260" y="10" width="100" height="100" filter="url(#f3)" stroke="blue"/>
+    <rect x="260" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="250" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="10" y="135" width="100" height="100" filter="url(#f4)" stroke="blue"/>
+    <rect x="10" y="135" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="00" y="125" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="135" y="135" width="100" height="100" filter="url(#f5)" stroke="blue"/>
+    <rect x="135" y="135" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="125" y="125" width="120" height="120" fill="none" stroke="green"/>
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/feImage-orientation.tentative.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/feImage-orientation.tentative.html
new file mode 100644
index 0000000..f45ecf1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/feImage-orientation.tentative.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Filter Effects: feImage respects EXIF orientation data</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/filter-effects-2/">
+<link rel="match" href="reference/feImage-orientation-ref.html">
+<meta name=fuzzy content="0-5;0-1115">
+</head>
+<body>
+  <svg style="width: 500px; height: 650px">
+    <defs>
+      <filter id="f1" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-1-ul.jpg"/></filter>
+      <filter id="f2" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-2-ur.jpg"/></filter>
+      <filter id="f3" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-3-lr.jpg"/></filter>
+      <filter id="f4" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-4-lol.jpg"/></filter>
+      <filter id="f5" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-5-lu.jpg"/></filter>
+      <filter id="f6" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-6-ru.jpg"/></filter>
+      <filter id="f7" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-7-rl.jpg"/></filter>
+      <filter id="f8" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-8-llo.jpg"/></filter>
+      <filter id="f9" primitiveUnits="objectBoundingBox"><feImage href="../css-images/image-orientation/support/exif-orientation-9-u.jpg"/></filter>
+    </defs>
+    <rect x="10" y="10" width="100" height="100" filter="url(#f1)"/>
+    <rect x="10" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="00" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="135" y="10" width="100" height="100" filter="url(#f2)" stroke="blue"/>
+    <rect x="135" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="125" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="260" y="10" width="100" height="100" filter="url(#f3)" stroke="blue"/>
+    <rect x="260" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="250" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="10" y="135" width="100" height="100" filter="url(#f4)" stroke="blue"/>
+    <rect x="10" y="135" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="00" y="125" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="135" y="135" width="100" height="100" filter="url(#f5)" stroke="blue"/>
+    <rect x="135" y="135" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="125" y="125" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="260" y="135" width="100" height="100" filter="url(#f6)" stroke="blue"/>
+    <rect x="260" y="135" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="250" y="125" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="10" y="260" width="100" height="100" filter="url(#f7)" stroke="blue"/>
+    <rect x="10" y="260" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="00" y="250" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="135" y="260" width="100" height="100" filter="url(#f6)" stroke="blue"/>
+    <rect x="135" y="260" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="125" y="250" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="260" y="260" width="100" height="100" filter="url(#f8)" stroke="blue"/>
+    <rect x="260" y="260" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="250" y="250" width="120" height="120" fill="none" stroke="green"/>
+  </svg>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/feImage-orientation-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/feImage-orientation-ref.html
new file mode 100644
index 0000000..3a1f6b29
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/feImage-orientation-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Filter Effects: feImage respects EXIF orientation data</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/filter-effects-2/">
+</head>
+<body>
+  <svg style="width: 500px; height: 650px">
+    <defs>
+      <filter id="f1" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-1-ul-pre-rotated.jpg"/></filter>
+      <filter id="f2" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-2-ur-pre-rotated.jpg"/></filter>
+      <filter id="f3" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-3-lr-pre-rotated.jpg"/></filter>
+      <filter id="f4" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-4-lol-pre-rotated.jpg"/></filter>
+      <filter id="f5" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-5-lu-pre-rotated.jpg"/></filter>
+      <filter id="f6" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-6-ru-pre-rotated.jpg"/></filter>
+      <filter id="f7" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-7-rl-pre-rotated.jpg"/></filter>
+      <filter id="f8" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-8-llo-pre-rotated.jpg"/></filter>
+      <filter id="f9" primitiveUnits="objectBoundingBox"><feImage href="../../css-images/image-orientation/support/exif-orientation-9-u-pre-rotated.jpg"/></filter>
+    </defs>
+    <rect x="10" y="10" width="100" height="100" filter="url(#f1)"/>
+    <rect x="10" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="00" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="135" y="10" width="100" height="100" filter="url(#f2)" stroke="blue"/>
+    <rect x="135" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="125" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="260" y="10" width="100" height="100" filter="url(#f3)" stroke="blue"/>
+    <rect x="260" y="10" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="250" y="00" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="10" y="135" width="100" height="100" filter="url(#f4)" stroke="blue"/>
+    <rect x="10" y="135" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="00" y="125" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="135" y="135" width="100" height="100" filter="url(#f5)" stroke="blue"/>
+    <rect x="135" y="135" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="125" y="125" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="260" y="135" width="100" height="100" filter="url(#f6)" stroke="blue"/>
+    <rect x="260" y="135" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="250" y="125" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="10" y="260" width="100" height="100" filter="url(#f7)" stroke="blue"/>
+    <rect x="10" y="260" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="00" y="250" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="135" y="260" width="100" height="100" filter="url(#f6)" stroke="blue"/>
+    <rect x="135" y="260" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="125" y="250" width="120" height="120" fill="none" stroke="green"/>
+
+    <rect x="260" y="260" width="100" height="100" filter="url(#f8)" stroke="blue"/>
+    <rect x="260" y="260" width="100" height="100" fill="none" stroke="blue"/>
+    <rect x="250" y="250" width="120" height="120" fill="none" stroke="green"/>
+  </svg>
+</body>
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.