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 <[email protected]> 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 <[email protected]> Commit-Queue: Stephen Chenney <[email protected]> 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:[email protected]"> +<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:[email protected]"> +<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:[email protected]"> +<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:[email protected]"> +<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