Chrome · ReaderMode
CVE-2026-78980
Logic Error in ReaderMode
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifcomponents/dom_distiller/core/javascript/content_processing.js |
modified | |
suitecomponents/test/data/dom_distiller/content_processing_tester.js |
modified |
Files Changed
components/dom_distiller/core/javascript/content_processing.jscomponents/test/data/dom_distiller/content_processing_tester.js
Patch
From 558ee3257125495bfbfefb1bc5cbd16602861ea8 Mon Sep 17 00:00:00 2001 From: Quentin Pubert <[email protected]> Date: Mon, 06 Jul 2026 08:28:57 -0700 Subject: [PATCH] [Reader Mode] Fix sanitizeLinks() bypass via SVG <a> with xlink:href In components/dom_distiller/core/javascript/content_processing.js, sanitizeLinks() previously checked only linkElement.getAttribute('href'). For SVG <a> elements using xlink:href, getAttribute('href') returns null, causing sanitizeLinks() to skip sanitizing the element. This change updates sanitizeLinks() to also check for the namespaced xlink:href attribute via getAttributeNS('http://www.w3.org/1999/xlink', 'href'). Also adds regression unit tests to content_processing_tester.js. Fixed: 523237735 Change-Id: I1c03459b6fd7a38910c002f88267189149168fd5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8025111 Reviewed-by: Olivier Robin <[email protected]> Commit-Queue: Matthew Jones <[email protected]> Reviewed-by: Matthew Jones <[email protected]> Auto-Submit: Quentin Pubert <[email protected]> Cr-Commit-Position: refs/heads/main@{#1657211} --- diff --git a/components/dom_distiller/core/javascript/content_processing.js b/components/dom_distiller/core/javascript/content_processing.js index 2445f16..1b521108 100644 --- a/components/dom_distiller/core/javascript/content_processing.js +++ b/components/dom_distiller/core/javascript/content_processing.js @@ -11,7 +11,8 @@ const allLinks = element.querySelectorAll('a'); allLinks.forEach(linkElement => { - const href = linkElement.getAttribute('href'); + const href = linkElement.getAttribute('href') || + linkElement.getAttributeNS('http://www.w3.org/1999/xlink', 'href'); if (href) { let keepLink = false; diff --git a/components/test/data/dom_distiller/content_processing_tester.js b/components/test/data/dom_distiller/content_processing_tester.js index 519d5a5..e6ddc5e 100644 --- a/components/test/data/dom_distiller/content_processing_tester.js +++ b/components/test/data/dom_distiller/content_processing_tester.js @@ -82,6 +82,37 @@ assert.equal(links.length, 0); assert.equal(testContainer.innerHTML, 'Mailto Link'); }); + + test( + 'sanitizeLinks should remove javascript SVG links with xlink:href', + async function() { + const {assert} = await import('./index.js'); + testContainer.innerHTML = '<svg><a xlink:href="javascript:void(0)">' + + '<text>SVG JS Link</text></a></svg>'; + sanitizeLinks(testContainer); + const links = testContainer.querySelectorAll('a'); + assert.equal(links.length, 0); + assert.equal( + testContainer.querySelector('svg').innerHTML, + '<text>SVG JS Link</text>'); + }); + + test( + 'sanitizeLinks should keep valid http/https SVG links with xlink:href ' + + 'and open in new tab', + async function() { + const {assert} = await import('./index.js'); + testContainer.innerHTML = + '<svg><a xlink:href="https://example.com">' + + '<text>SVG HTTPS Link</text></a></svg>'; + sanitizeLinks(testContainer); + const links = testContainer.querySelectorAll('a'); + assert.equal(links.length, 1); + assert.equal( + links[0].getAttributeNS('http://www.w3.org/1999/xlink', 'href'), + 'https://example.com'); + assert.equal(links[0].target, '_blank'); + }); }); suite('ContentProcessing.removeExtraneousElementsFrom', function() {
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/components/test/data/dom_distiller/content_processing_tester.js b/components/test/data/dom_distiller/content_processing_tester.js
index 519d5a5..e6ddc5e 100644
--- a/components/test/data/dom_distiller/content_processing_tester.js
+++ b/components/test/data/dom_distiller/content_processing_tester.js
@@ -82,6 +82,37 @@
assert.equal(links.length, 0);
assert.equal(testContainer.innerHTML, 'Mailto Link');
});
+
+ test(
+ 'sanitizeLinks should remove javascript SVG links with xlink:href',
+ async function() {
+ const {assert} = await import('./index.js');
+ testContainer.innerHTML = '<svg><a xlink:href="javascript:void(0)">' +
+ '<text>SVG JS Link</text></a></svg>';
+ sanitizeLinks(testContainer);
+ const links = testContainer.querySelectorAll('a');
+ assert.equal(links.length, 0);
+ assert.equal(
+ testContainer.querySelector('svg').innerHTML,
+ '<text>SVG JS Link</text>');
+ });
+
+ test(
+ 'sanitizeLinks should keep valid http/https SVG links with xlink:href ' +
+ 'and open in new tab',
+ async function() {
+ const {assert} = await import('./index.js');
+ testContainer.innerHTML =
+ '<svg><a xlink:href="https://example.com">' +
+ '<text>SVG HTTPS Link</text></a></svg>';
+ sanitizeLinks(testContainer);
+ const links = testContainer.querySelectorAll('a');
+ assert.equal(links.length, 1);
+ assert.equal(
+ links[0].getAttributeNS('http://www.w3.org/1999/xlink', 'href'),
+ 'https://example.com');
+ assert.equal(links[0].target, '_blank');
+ });
});
suite('ContentProcessing.removeExtraneousElementsFrom', function() {
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