Chrome · SplitView
CVE-2025-12446
Logic Error in SplitView
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifchrome/browser/resources/tab_search/tab_search_page.ts |
modified |
Files Changed
chrome/browser/resources/tab_search/tab_search_item.csschrome/browser/resources/tab_search/tab_search_page.tschrome/browser/ui/webui/tab_search/tab_search_ui.ccchrome/test/data/webui/tab_search/tab_search_page_test.ts
Patch
From 5afd445e6deae19de5bf3629b451cea29a7b860e Mon Sep 17 00:00:00 2001 From: Alison Gale <[email protected]> Date: Wed, 17 Sep 2025 12:56:50 -0700 Subject: [PATCH] [SxS] Fix URL eliding for tab search Show "temporary data" for blob: URLs and "local or shared file" for file: URLs to match what we do for hovercards and mini toolbar. Elide URLs from the front to avoid spoofing with long subdomains. Before: https://screenshot.googleplex.com/BFA7KaDQtYpR5ZH After: https://screenshot.googleplex.com/3e9uyAMCfZxxSHL Guidelines: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/security/url_display_guidelines/url_display_guidelines.md#eliding-urls Bug: 444932667,444915898 Change-Id: Id3a540eaa4392a85f9db2d0b5424d009a1bd271c Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6956837 Reviewed-by: Chris Thompson <[email protected]> Reviewed-by: Yuheng Huang <[email protected]> Commit-Queue: Alison Gale <[email protected]> Cr-Commit-Position: refs/heads/main@{#1516831} --- diff --git a/chrome/browser/resources/tab_search/tab_search_item.css b/chrome/browser/resources/tab_search/tab_search_item.css index 8a06e14e..5b3a2ae1 100644 --- a/chrome/browser/resources/tab_search/tab_search_item.css +++ b/chrome/browser/resources/tab_search/tab_search_item.css @@ -79,6 +79,11 @@ white-space: nowrap; } +#secondaryText { + /* Elide hostname from the front to prevent URL spoofing. */ + direction: rtl; +} + #primaryText { color: var(--cr-primary-text-color); font-size: var(--mwb-primary-text-font-size); diff --git a/chrome/browser/resources/tab_search/tab_search_page.ts b/chrome/browser/resources/tab_search/tab_search_page.ts index c58fdc3..3dbd50776 100644 --- a/chrome/browser/resources/tab_search/tab_search_page.ts +++ b/chrome/browser/resources/tab_search/tab_search_page.ts @@ -661,11 +661,22 @@ return ariaLabel(tabData); } + private getDisplayHostnameForUrl_(url: URL): string { + if (url.protocol === 'blob:') { + return loadTimeData.getString('blobUrlSource'); + } else if (url.protocol === 'file:') { + return loadTimeData.getString('fileUrlSource'); + } else { + return url.hostname; + } + } + private tabData_( tab: Tab|RecentlyClosedTab, inActiveWindow: boolean, type: TabItemType, tabGroupsMap: Map<string, TabGroup>): TabData { - const tabData = - new TabData(tab, type, new URL(normalizeURL(tab.url.url)).hostname); + const tabData = new TabData( + tab, type, + this.getDisplayHostnameForUrl_(new URL(normalizeURL(tab.url.url)))); if (tab.groupId) { tabData.tabGroup = tabGroupsMap.get(tokenToString(tab.groupId)); diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc index c3c82b31..f30546bc 100644 --- a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc +++ b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc @@ -79,10 +79,12 @@ IDS_TAB_SEARCH_A11Y_RECENTLY_CLOSED_TAB_GROUP}, {"audioMuting", IDS_TAB_AX_LABEL_AUDIO_MUTING_FORMAT}, {"audioPlaying", IDS_TAB_AX_LABEL_AUDIO_PLAYING_FORMAT}, + {"blobUrlSource", IDS_HOVER_CARD_BLOB_URL_SOURCE}, {"clearSearch", IDS_CLEAR_SEARCH}, {"closeTab", IDS_TAB_SEARCH_CLOSE_TAB}, {"collapseRecentlyClosed", IDS_TAB_SEARCH_COLLAPSE_RECENTLY_CLOSED}, {"expandRecentlyClosed", IDS_TAB_SEARCH_EXPAND_RECENTLY_CLOSED}, + {"fileUrlSource", IDS_HOVER_CARD_FILE_URL_SOURCE}, {"mediaRecording", IDS_TAB_AX_LABEL_MEDIA_RECORDING_FORMAT}, {"audioRecording", IDS_TAB_AX_LABEL_AUDIO_RECORDING_FORMAT}, {"videoRecording", IDS_TAB_AX_LABEL_VIDEO_RECORDING_FORMAT}, diff --git a/chrome/test/data/webui/tab_search/tab_search_page_test.ts b/chrome/test/data/webui/tab_search/tab_search_page_test.ts index b91f9ca..5183ed0 100644 --- a/chrome/test/data/webui/tab_search/tab_search_page_test.ts +++ b/chrome/test/data/webui/tab_search/tab_search_page_test.ts @@ -4,6 +4,7 @@ import 'chrome://tab-search.top-chrome/tab_search.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {MetricsReporterImpl} from 'chrome://resources/js/metrics_reporter/metrics_reporter.js'; import type {ProfileData, RecentlyClosedTab, Tab, TabSearchItemElement, TabSearchPageElement} from 'chrome://tab-search.top-chrome/tab_search.js'; import {SEARCH_QUERY_MAX_LENGTH, TabGroupColor, TabSearchApiProxyImpl} from 'chrome://tab-search.top-chrome/tab_search.js'; @@ -844,4 +845,42 @@ const [tabInfo] = await testProxy.whenCalled('switchToTab'); assertEquals(1, tabInfo.tabId); }); + + test('Handles file URLs', async () => { + await setupTest(createProfileData({ + windows: [{ + active: true, + isHostWindow: true, + height: SAMPLE_WINDOW_HEIGHT, + tabs: [createTab({ + title: 'My file', + url: {url: 'file:///home'}, + lastActiveTimeTicks: {internalValue: BigInt(4)}, + })], + }], + })); + const tabSearchItem = + tabSearchPage.$.tabsList.querySelector('tab-search-item')!; + assertEquals( + loadTimeData.getString('fileUrlSource'), tabSearchItem.data.hostname); + }); + + test('Handles blob URLs', async () => { + await setupTest(createProfileData({ + windows: [{ + active: true, + isHostWindow: true, + height: SAMPLE_WINDOW_HEIGHT, + tabs: [createTab({ + title: 'My blob', + url: {url: 'blob:null/foo'}, + lastActiveTimeTicks: {internalValue: BigInt(4)}, + })], + }], + })); + const tabSearchItem = + tabSearchPage.$.tabsList.querySelector('tab-search-item')!; + assertEquals( + loadTimeData.getString('blobUrlSource'), tabSearchItem.data.hostname); + }); });
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/test/data/webui/tab_search/tab_search_page_test.ts b/chrome/test/data/webui/tab_search/tab_search_page_test.ts
index b91f9ca..5183ed0 100644
--- a/chrome/test/data/webui/tab_search/tab_search_page_test.ts
+++ b/chrome/test/data/webui/tab_search/tab_search_page_test.ts
@@ -4,6 +4,7 @@
import 'chrome://tab-search.top-chrome/tab_search.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {MetricsReporterImpl} from 'chrome://resources/js/metrics_reporter/metrics_reporter.js';
import type {ProfileData, RecentlyClosedTab, Tab, TabSearchItemElement, TabSearchPageElement} from 'chrome://tab-search.top-chrome/tab_search.js';
import {SEARCH_QUERY_MAX_LENGTH, TabGroupColor, TabSearchApiProxyImpl} from 'chrome://tab-search.top-chrome/tab_search.js';
@@ -844,4 +845,42 @@
const [tabInfo] = await testProxy.whenCalled('switchToTab');
assertEquals(1, tabInfo.tabId);
});
+
+ test('Handles file URLs', async () => {
+ await setupTest(createProfileData({
+ windows: [{
+ active: true,
+ isHostWindow: true,
+ height: SAMPLE_WINDOW_HEIGHT,
+ tabs: [createTab({
+ title: 'My file',
+ url: {url: 'file:///home'},
+ lastActiveTimeTicks: {internalValue: BigInt(4)},
+ })],
+ }],
+ }));
+ const tabSearchItem =
+ tabSearchPage.$.tabsList.querySelector('tab-search-item')!;
+ assertEquals(
+ loadTimeData.getString('fileUrlSource'), tabSearchItem.data.hostname);
+ });
+
+ test('Handles blob URLs', async () => {
+ await setupTest(createProfileData({
+ windows: [{
+ active: true,
+ isHostWindow: true,
+ height: SAMPLE_WINDOW_HEIGHT,
+ tabs: [createTab({
+ title: 'My blob',
+ url: {url: 'blob:null/foo'},
+ lastActiveTimeTicks: {internalValue: BigInt(4)},
+ })],
+ }],
+ }));
+ const tabSearchItem =
+ tabSearchPage.$.tabsList.querySelector('tab-search-item')!;
+ assertEquals(
+ loadTimeData.getString('blobUrlSource'), tabSearchItem.data.hostname);
+ });
});
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