Low watch CVSS 5.4 chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Low
Severity
5.4
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInappropriate implementation in Tab Strip
DescriptionInappropriate implementation in Tab Strip
ComponentTab Strip
Sub-componentUI>Browser>TopChrome>TabStrip>HoverCards
Bug ClassLogic Error
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker40075024
Fix commitd9a315b74c66 (chromium/src) +4/-2
CWECWE-290
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N
CISA KEVNot listed
CreditedKhalil Zhani
Reported2023-10-17 · bounty $500 (per vendor advisory)
Fix landed2025-04-16 (public git)
Disclosed2025-05-27
Patch gap41 days — fix public in source before the advisory

Background

Tab hover card
the bubble (TabHoverCardBubbleView) shown when hovering a tab, displaying the page title and, on a separate domain_label_, the URL’s domain.
`gfx::ElideBehavior`
an enum controlling how text too wide for its label is truncated: ELIDE_TAIL cuts the end (keeping the start), while ELIDE_HEAD cuts the start (keeping the end).
`FadeLabelViewData`
the small struct carrying a label’s text, is_filename flag, and (after the patch) an elide behavior into FadeLabelView::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.

Key insight
The core mistake was eliding the tail of the domain label, which discards the trust-defining registrable domain and keeps attacker-controlled subdomains; the fix switches the domain label to ELIDE_HEAD so the domain is always preserved.

Attack Path

  1. 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).
  2. Get the URL rendered in a tab The victim opens/keeps a tab pointing at this URL so the tab’s domain string is long enough to require elision in the hover card.
  3. Hover to display the card Hovering the tab invokes the hover-card update path, which set the domain label with ELIDE_TAIL semantics.
  4. 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

An attacker gains the ability to spoof the domain shown in the tab hover card by exploiting tail elision to hide the registrable domain behind attacker-chosen subdomains, an “inappropriate implementation” (LogicError) in the Tab Strip UI running in the browser process. The precondition is that the victim opens the crafted URL and hovers the tab; the impact is user deception, not code execution, and any further consequence (e.g. phishing success) is (inferred). The advisory does not report in-the-wild exploitation.

Changed Functions

FunctionChangeNotes
if
chrome/browser/ui/views/tabs/fade_label_view.cc
modified

Files Changed

  • chrome/browser/ui/views/tabs/fade_label_view.cc
  • chrome/browser/ui/views/tabs/fade_label_view.h
  • chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc

Audit Directions

  • URL/origin truncation
    Audit 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 defaults
    Search 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 threading
    When 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.
From d9a315b74c6648f185aec28d99bf824ddd86f48f Mon Sep 17 00:00:00 2001
From: David Pennington <[email protected]>
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 <[email protected]>
Commit-Queue: David Pennington <[email protected]>
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);
Loading diff…

Original Bug Report

reported by [email protected]

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

  1. Go to https://long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com
  2. Hover over the tab
View on issue tracker