Chrome · SVG
CVE-2026-17942
Logic Error in SVG
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifthird_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.ccthird_party/blink/renderer/platform/runtime_enabled_features.json5third_party/blink/web_tests/external/wpt/css/filter-effects/feImage-orientation.tentative.htmlthird_party/blink/web_tests/external/wpt/css/filter-effects/reference/feImage-orientation-ref.html
Patch
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.
References
On This Page