CVE-2025-5067
Overview
Background
- Tab hover card
- the bubble (
TabHoverCardBubbleView) shown when hovering a tab, displaying the page title and, on a separatedomain_label_, the URL’s domain. - `gfx::ElideBehavior`
- an enum controlling how text too wide for its label is truncated:
ELIDE_TAILcuts the end (keeping the start), whileELIDE_HEADcuts the start (keeping the end). - `FadeLabelViewData`
- the small struct carrying a label’s
text,is_filenameflag, and (after the patch) anelidebehavior intoFadeLabelView::SetData. - Registrable domain
- the security-significant part of a hostname (e.g.
example.com), which in a left-to-right host string appears at the tail, after any subdomains.
Root Cause Analysis
The hover card’s domain label was populated via domain_label_->SetData({domain, false}), and FadeLabelView::SetData hard-coded the elision to gfx::ELIDE_TAIL for any non-filename text. When a domain string was too long to fit, ELIDE_TAIL truncated the end — precisely the registrable domain — while preserving the leading subdomain labels. This violates the invariant that the security-relevant portion of a URL (the actual domain) must remain visible; an attacker could craft a hostname whose long, benign-looking subdomain prefix survives and whose true domain is elided away, misleading the user about the site’s origin.
The fix threads an elide field through FadeLabelViewData (defaulting to ELIDE_TAIL for backward compatibility) and has the caller pass gfx::ELIDE_HEAD for the domain label, so truncation now removes the leading subdomains and keeps the domain at the tail visible. FadeLabelView::SetData was updated to honor data.elide instead of the fixed ELIDE_TAIL.
ELIDE_HEAD so the domain is always preserved.Attack Path
- Craft a spoofing hostname An attacker hosts content on a domain with a long subdomain chain designed to resemble a trusted site (e.g. a legitimate-looking prefix followed by the real, attacker-controlled domain).
- Get the URL rendered in a tab
The victim opens/keeps a tab pointing at this URL so the tab’s
domainstring is long enough to require elision in the hover card. - Hover to display the card
Hovering the tab invokes the hover-card update path, which set the domain label with
ELIDE_TAILsemantics. - Domain is hidden Tail elision truncates the real domain and leaves the misleading subdomain prefix visible, so the user misjudges the site’s identity (URL/origin spoofing). No memory-safety issue is involved.
Impact Assessment
(inferred). The advisory does not report in-the-wild exploitation.Changed Functions
| Function | Change | Notes |
|---|---|---|
ifchrome/browser/ui/views/tabs/fade_label_view.cc |
modified |
Files Changed
chrome/browser/ui/views/tabs/fade_label_view.ccchrome/browser/ui/views/tabs/fade_label_view.hchrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
Audit Directions
- URL/origin truncationAudit every UI surface that shows hostnames or URLs (omnibox chips, permission prompts, bubbles, page-info) for elision that could drop the registrable domain instead of subdomains or path.
- Hard-coded elision defaultsSearch for
SetElideBehavior(... ELIDE_TAIL)or similar defaults applied to security-relevant strings, and verify head elision (or middle elision) is used where the tail carries the trust decision. - Struct-defaulted behavior threadingWhen a display option is threaded through a data struct with a default (like
FadeLabelViewData::elide), check all call sites to confirm security-sensitive ones override the default rather than silently inheriting the insecure value.
Patch
From d9a315b74c6648f185aec28d99bf824ddd86f48f Mon Sep 17 00:00:00 2001
From: David Pennington <dpenning@chromium.org>
Date: Wed, 16 Apr 2025 13:05:27 -0700
Subject: [PATCH] Move elide to head for the domain for security purposes
Domain is much more important than the subdomains, thus when showing the
URL we prioritize domain by eliding the head.
Fixed: 40075024
Change-Id: I48e725e32f746b4aa7bb92871a7b6c32d61d3037
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6461121
Reviewed-by: Steven Luong <stluong@chromium.org>
Commit-Queue: David Pennington <dpenning@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1447960}
---
diff --git a/chrome/browser/ui/views/tabs/fade_label_view.cc b/chrome/browser/ui/views/tabs/fade_label_view.cc
index 153f1ab..0e667cf 100644
--- a/chrome/browser/ui/views/tabs/fade_label_view.cc
+++ b/chrome/browser/ui/views/tabs/fade_label_view.cc
@@ -23,7 +23,7 @@
data_ = data;
std::u16string text = data.text;
const bool is_filename = data.is_filename;
- SetElideBehavior(is_filename ? gfx::NO_ELIDE : gfx::ELIDE_TAIL);
+ SetElideBehavior(is_filename ? gfx::NO_ELIDE : data.elide);
if (is_filename) {
text = TruncateFilenameToTwoLines(text);
}
diff --git a/chrome/browser/ui/views/tabs/fade_label_view.h b/chrome/browser/ui/views/tabs/fade_label_view.h
index c55f942..7be4669 100644
--- a/chrome/browser/ui/views/tabs/fade_label_view.h
+++ b/chrome/browser/ui/views/tabs/fade_label_view.h
@@ -9,6 +9,7 @@
#include "chrome/browser/ui/views/tabs/fade_view.h"
#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/gfx/text_constants.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/label.h"
#include "ui/views/style/typography.h"
@@ -16,6 +17,7 @@
struct FadeLabelViewData {
std::u16string text;
bool is_filename = false;
+ gfx::ElideBehavior elide = gfx::ELIDE_TAIL;
};
using FadeWrapper_Label_FadeLabelViewData =
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
index 0344029..d330df32 100644
--- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
+++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -572,7 +572,7 @@
}
title_label_->SetData({title, is_filename});
- domain_label_->SetData({domain, false});
+ domain_label_->SetData({domain, false, gfx::ELIDE_HEAD});
CollaborationMessagingRowData collaboration_messaging_data =
GetCollaborationMessagingData(tab_data);
Original Bug Report
Security: Popup window tab doesn't show the origin elided from the right
VERSION
Chrome Version: 120.0.6071.0 (Official Build) canary (64-bit) (cohort: Clang-64)
Operating System: Windows 11
REPRODUCTION CASE
- Go to https://long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com
- Hover over the tab