Chrome · Permissions
CVE-2026-5905
Logic Error in Permissions
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Fchrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc |
modified |
Files Changed
chrome/browser/ui/content_settings/content_setting_bubble_model.ccchrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
Patch
From 848a7a9f1feeba1debc2abfc9b9b1b38ec2b28d1 Mon Sep 17 00:00:00 2001 From: Nathan Parker <[email protected]> Date: Thu, 19 Feb 2026 08:18:27 -0800 Subject: [PATCH] Fix URL spoofing on "Pop-ups blocked" dialog in Chrome. Switched to FormatUrl() which removes the username:password@ component. Example of new formatting, with hover: http://screen/M4wV4PuQ4vu2zDr Bug: 483899628 Change-Id: Iff473a1718f7f4662abddbeff29223973c7de845 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7577181 Reviewed-by: Ravjit Uppal <[email protected]> Commit-Queue: Nathan Parker <[email protected]> Cr-Commit-Position: refs/heads/main@{#1587161} --- diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc index 306b3d8..45fc4ca6 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc @@ -68,6 +68,7 @@ #include "components/subresource_filter/core/browser/subresource_filter_constants.h" #include "components/subresource_filter/core/browser/subresource_filter_features.h" #include "components/url_formatter/elide_url.h" +#include "components/url_formatter/url_formatter.h" #include "components/vector_icons/vector_icons.h" #include "content/public/browser/page.h" #include "content/public/browser/permission_controller.h" @@ -171,10 +172,12 @@ const GURL& url) { // Empty URLs should get a placeholder. // TODO(csharrison): See if we can DCHECK that the URL will be valid here. - std::u16string title = url.spec().empty() - ? l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) - : base::UTF8ToUTF16(url.spec()); - + std::u16string title = + url.spec().empty() + ? l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) + : url_formatter::FormatUrl( + url, url_formatter::kFormatUrlOmitUsernamePassword, + base::UnescapeRule::NONE, nullptr, nullptr, nullptr); // Format the title to include the unicode single dot bullet code-point // \u2022 and two spaces. title = l10n_util::GetStringFUTF16(IDS_LIST_BULLET, title); diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc index 10f443bb..ae12051 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc @@ -1391,6 +1391,44 @@ } } +TEST_F(ContentSettingBubbleModelTest, PopupBubbleModelListItemsSpoofing) { + const GURL url("https://www.example.test/"); + WebContentsTester::For(web_contents())->NavigateAndCommit(url); + blocked_content::PopupBlockerTabHelper::CreateForWebContents(web_contents()); + + // Malicious URL + GURL spoof_url("http://google.com:[email protected]"); + + BlockedWindowParams params(spoof_url, url::Origin(), nullptr, + content::Referrer(), std::string(), + WindowOpenDisposition::NEW_POPUP, + blink::mojom::WindowFeatures(), false, true); + + NavigateParams navigate_params = + params.CreateNavigateParams(process(), web_contents()); + blocked_content::MaybeBlockPopup( + web_contents(), &url, + std::make_unique<ChromePopupNavigationDelegate>( + std::move(navigate_params)), + nullptr, params.features(), + HostContentSettingsMapFactory::GetForProfile(profile())); + + std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model( + ContentSettingBubbleModel::CreateContentSettingBubbleModel( + nullptr, web_contents(), ContentSettingsType::POPUPS)); + + const auto& list_items = + content_setting_bubble_model->bubble_content().list_items; + ASSERT_EQ(1U, list_items.size()); + + // Check the title + std::u16string title = list_items[0].title; + // It should NOT contain "google.com" if it's formatted correctly for + // security. + EXPECT_EQ(std::u16string::npos, title.find(u"google.com")); + EXPECT_NE(std::u16string::npos, title.find(u"evil.com")); +} + TEST_F(ContentSettingBubbleModelTest, ValidUrl) { WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com"));
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
index 10f443bb..ae12051 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
@@ -1391,6 +1391,44 @@
}
}
+TEST_F(ContentSettingBubbleModelTest, PopupBubbleModelListItemsSpoofing) {
+ const GURL url("https://www.example.test/");
+ WebContentsTester::For(web_contents())->NavigateAndCommit(url);
+ blocked_content::PopupBlockerTabHelper::CreateForWebContents(web_contents());
+
+ // Malicious URL
+ GURL spoof_url("http://google.com:[email protected]");
+
+ BlockedWindowParams params(spoof_url, url::Origin(), nullptr,
+ content::Referrer(), std::string(),
+ WindowOpenDisposition::NEW_POPUP,
+ blink::mojom::WindowFeatures(), false, true);
+
+ NavigateParams navigate_params =
+ params.CreateNavigateParams(process(), web_contents());
+ blocked_content::MaybeBlockPopup(
+ web_contents(), &url,
+ std::make_unique<ChromePopupNavigationDelegate>(
+ std::move(navigate_params)),
+ nullptr, params.features(),
+ HostContentSettingsMapFactory::GetForProfile(profile()));
+
+ std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model(
+ ContentSettingBubbleModel::CreateContentSettingBubbleModel(
+ nullptr, web_contents(), ContentSettingsType::POPUPS));
+
+ const auto& list_items =
+ content_setting_bubble_model->bubble_content().list_items;
+ ASSERT_EQ(1U, list_items.size());
+
+ // Check the title
+ std::u16string title = list_items[0].title;
+ // It should NOT contain "google.com" if it's formatted correctly for
+ // security.
+ EXPECT_EQ(std::u16string::npos, title.find(u"google.com"));
+ EXPECT_NE(std::u16string::npos, title.find(u"evil.com"));
+}
+
TEST_F(ContentSettingBubbleModelTest, ValidUrl) {
WebContentsTester::For(web_contents())
->NavigateAndCommit(GURL("https://www.example.com"));
Loading diff…
Original Bug Report
reported by [email protected]
URL Spoofing on Block or allow pop-ups in Chrome
Steps to reproduce the problem
- Save this 2 HTML files (orig.html and fake.html) and analyze the link in the popup message, it looks the same
- Allow the popup
- The victim redirected to evil.com instead of google.com
Problem Description
When using window.open, Chrome shows a popup listing temporarily blocked URLs and waits for the user’s approval. If a suspicious URL is detected, the user can choose to keep it blocked. However, in this popup Chrome displays only the URL’s prefix and suffix. By inserting a malicious URL in the middle using @, an attacker can disguise it. If the user allows the popup, instead of opening a safe website, Chrome will open the malicious URL.
Summary
URL Spoofing on Block or allow pop-ups in Chrome
Additional Data
Category: Security
Chrome Channel: Not sure
Regression: N/A \
References
On This Page