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 <nparker@chromium.org>
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 <ravjit@chromium.org>
Commit-Queue: Nathan Parker <nparker@chromium.org>
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:VeryLongString@evil.com");
+
+ 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:VeryLongString@evil.com");
+
+ 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 mu...@gmail.com
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