CVE-2026-8021
Overview
Background
- Home button
- the toolbar control whose target URL is stored in the
prefs::kHomePagepreference and loaded in the current tab when clicked. - `javascript:` URL
- a pseudo-scheme (
url::kJavaScriptScheme) whose body is executed as script in the context of the page it is navigated to. - Drag-and-drop URL drop
- dropping a link onto a UI target hands the target a
ui::ClipboardUrlInfolist viaevent.data().GetURLs(...). - Self-XSS
- tricking a user into injecting script into their own session, here by making a
javascript:URL the persistent home page.
Root Cause Analysis
The drop handler that updates the home page read the first dropped URL, asserted only that it was valid (CHECK(url_infos.front().url.is_valid())), and wrote it directly into prefs::kHomePage. No scheme filtering was applied, so a javascript: URL dragged onto the home button was accepted and stored as the home page. On a later Home-button click the stored javascript: URL would execute as script in whatever document was then loaded, giving script injection.
The fix captures new_homepage and returns early when new_homepage.SchemeIs(url::kJavaScriptScheme), so the dangerous scheme is rejected before any preference is written; the validity CHECK is kept, just moved up.
The patch TIGHTENS the accepted-input set (a scheme is now disallowed that was previously allowed).
javascript: home page; the fix adds an explicit kJavaScriptScheme rejection before prefs_->SetString(prefs::kHomePage, ...).Attack Path
- Craft a `javascript:` link
The attacker presents a page containing a draggable link whose href is a
javascript:payload. - Social-engineer a drop
The user is induced to drag that link onto the toolbar home button, invoking the drop handler with the
javascript:URL asurl_infos.front().url. - Persist as home page
Pre-patch, the handler stores the
javascript:URL intoprefs::kHomePageand setskHomePageIsNewTabPageto false, making it the standing home page. - Trigger execution
When the user later clicks Home, the stored
javascript:URL runs as script in the active document’s context, achieving self-XSS.
Impact Assessment
Files Changed
chrome/browser/ui/views/toolbar/home_button.cc
Audit Directions
- URL sinks that validate only `is_valid()`Search UI code that persists or navigates to user-supplied URLs; a validity check is not a scheme check, so each needs an explicit allow/deny of
javascript:(anddata:/blob:where relevant). - Drag-and-drop URL acceptorsReview other drop targets (home button, bookmarks, tabs, profile prefs) that accept
GetURLs(...)output for consistent dangerous-scheme filtering. - Preference-backed navigationsAudit preferences that later become navigation targets (home page, startup pages, new-tab overrides) for scheme sanitization at write time, not just at read time.
Patch
From b920b51115d9574401ecbee912839eabe622707e Mon Sep 17 00:00:00 2001 From: Mike West <[email protected]> Date: Wed, 01 Apr 2026 07:35:10 -0700 Subject: [PATCH] Prevent setting `javascript:` home page URLs. We allow `javascript:` URLs to be dragged into the bookmark bar, but we probably shouldn't allow the same for the home button. This CL adds a check to `HomeButton::UpdateHomePage()` to exclude those URLs. Bug: 498417031 Change-Id: I4f895e99340327156e53af6a4dbd6fcbd2c936e3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7717841 Reviewed-by: Elly FJ <[email protected]> Commit-Queue: Mike West <[email protected]> Cr-Commit-Position: refs/heads/main@{#1608519} --- diff --git a/chrome/browser/ui/views/toolbar/home_button.cc b/chrome/browser/ui/views/toolbar/home_button.cc index 09e1f7a..ba1b420 100644 --- a/chrome/browser/ui/views/toolbar/home_button.cc +++ b/chrome/browser/ui/views/toolbar/home_button.cc @@ -184,11 +184,18 @@ const std::vector<ui::ClipboardUrlInfo> url_infos = event.data().GetURLs(ui::FilenameToURLPolicy::CONVERT_FILENAMES); if (!url_infos.empty() && prefs_) { + GURL new_homepage = url_infos.front().url; + CHECK(new_homepage.is_valid()); + + // Disallow javascript: URLs to prevent self-XSS. + if (new_homepage.SchemeIs(url::kJavaScriptScheme)) { + return; + } + GURL old_homepage(prefs_->GetString(prefs::kHomePage)); bool old_is_ntp = prefs_->GetBoolean(prefs::kHomePageIsNewTabPage); - CHECK(url_infos.front().url.is_valid()); - prefs_->SetString(prefs::kHomePage, url_infos.front().url.spec()); + prefs_->SetString(prefs::kHomePage, new_homepage.spec()); prefs_->SetBoolean(prefs::kHomePageIsNewTabPage, false); coordinator_.Show(old_homepage, old_is_ntp);
Original Bug Report
Persistent Cross-Device UXSS via Home Button Drag-and-Drop
Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the security team.
Overview: The Home button’s drag-and-drop handler fails to filter javascript: URLs when setting the home page preference. This allows an attacker to persistently set a malicious javascript: payload as the user’s home page, which executes in the context of the active tab (UXSS) when the user navigates home.
Affected files:
chrome/browser/ui/views/toolbar/home_button.ccchrome/browser/ui/views/frame/browser_root_view.ccui/views/widget/drop_helper.cccontent/browser/renderer_host/render_widget_host_impl.ccthird_party/blink/renderer/core/frame/local_frame.cc
Estimated timestamp from git blame: 2026-01-26
Summary
There is a potential Persistent Universal Cross-Site Scripting (UXSS) vulnerability in the HomeButton component (chrome/browser/ui/views/toolbar/home_button.cc). By dragging a javascript: URL onto the Home button, an attacker can set it as the user’s home page preference (prefs::kHomePage). Because this preference is synced across devices, the payload becomes persistent and multi-device. When the user later triggers the ‘Home’ action (via click or Alt+Home), the javascript: URL is executed in the context of the currently active tab, bypassing Content Security Policy (CSP).
Vulnerability Details
- Missing Scheme Filter in HomeButton: When a user drags a URL onto the Home button, the
HomeButton::CanDropmethod returns true for any valid URL data. This causes theViews DropHelperto stop its upward traversal, bypassing the safety filters inBrowserRootView::FilterURLsForDropabilitythat explicitly blockjavascript:URLs to prevent self-XSS. - Unsafe Preference Write:
HomeButton::UpdateHomePagethen writes the dropped URL toprefs::kHomePageusing only aCHECK(is_valid())validation. It fails to perform scheme filtering, allowingjavascript:URLs to be saved. - Cross-Device Sync: The
kHomePagepreference is aSYNCABLE_PREF. The malicious URL is synchronized to all other desktop Chrome instances where the user is signed in. - Trigger and Execution: When the user clicks the Home button,
Home()(chrome/browser/ui/browser_commands.cc) reads the home page URL and callsOpenURLwithis_renderer_initiated = false. - Debug URL Processing:
NavigationControllerImplsees thejavascript:URL, identifies it as a renderer-debug URL (blink::IsRendererDebugURL), and routes it toHandleRendererDebugURL. - UXSS: The URL is sent via Mojo to the renderer’s
LocalFrame::LoadJavaScriptURL. The script executes in theMainWorldof the current page withCSPDisposition::DO_NOT_CHECK, resulting in UXSS on the active tab’s origin.
Potential Reproduction Steps
Please note: our tooling agent cannot run code, so these are suggested steps to verify the vulnerability.
- Enable ‘Show Home button’ in
chrome://settings/appearance. - Create and navigate to an attacker-controlled page with a draggable link containing a
javascript:payload:<a href="javascript:alert('UXSS: ' + document.domain)" draggable="true">Drag me to the Home button</a>. - Drag the link onto the Home button in the browser toolbar.
- Navigate to a sensitive website (e.g.,
https://example.com). - Press
Alt+Homeor click the Home button. - Observe that the JavaScript execution occurs in the context of the current site’s origin.
Suggested Fix
Modify HomeButton::CanDrop or HomeButton::UpdateHomePage to explicitly filter out javascript: URLs, similar to the existing protection in BrowserRootView::FilterURLsForDropability. For example:
void HomeButton::UpdateHomePage(...) {
// ... existing code ...
if (!url_infos.empty() && prefs_) {
GURL new_homepage = url_infos.front().url;
// Fix: Disallow javascript: URLs to prevent UXSS.
if (new_homepage.SchemeIs(url::kJavaScriptScheme)) {
return;
}
CHECK(new_homepage.is_valid());
prefs_->SetString(prefs::kHomePage, new_homepage.spec());
// ...
Evaluated with Chrome root at commit: ff3d2b74fa39431785bd60e51463b08fcc71ee33
Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.