CVE-2026-11177
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifchrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.cc |
modified |
Files Changed
chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.ccchrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.hchrome/browser/ui/webui/omnibox_popup/omnibox_popup_web_contents_helper.ccchrome/browser/ui/webui/searchbox/webui_omnibox_handler.ccchrome/browser/ui/webui/searchbox/webui_omnibox_handler.h
Patch
From 4d9007792d4ad8ba545ee28c2978a0aebcbfd2d0 Mon Sep 17 00:00:00 2001
From: Orin Jaworski <orinj@chromium.org>
Date: Thu, 16 Apr 2026 12:10:07 -0700
Subject: [PATCH] [omnibox] Reconnect OmniboxController etc. after tab changes windows
This CL fixes UAF crash and other issues caused by the webui omnibox
remaining connected to its original window after its tab is
moved to a different window. This applies to webui omniboxes
in tabs, chrome://omnibox-popup.top-chrome/ . It was previously
possible to move the tab to a different window and then see
autocomplete suggestions for input to the original window's
omnibox, which wasn't right. Now it stays connected only to the
current browser window, as expected.
Fixed: 502449864
Change-Id: I15475b487431a61d7278b92f72a17d91b636e147
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7766130
Reviewed-by: Ananya Seelam <ananyaseelam@google.com>
Commit-Queue: Orin Jaworski <orinj@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1616041}
---
diff --git a/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.cc b/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.cc
index 26e793f9..68b5bd4 100644
--- a/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.cc
+++ b/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.cc
@@ -315,6 +315,14 @@
}
}
+void ContextualSearchboxHandler::UpdateTabListObservation(
+ TabListInterface* tab_list) {
+ tab_list_observation_.Reset();
+ if (tab_list) {
+ tab_list_observation_.Observe(tab_list);
+ }
+}
+
void ContextualSearchboxHandler::OnTabAdded(TabListInterface& tab_list,
tabs::TabInterface* tab,
int index) {
diff --git a/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.h b/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.h
index e763b639..8b55be26 100644
--- a/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.h
+++ b/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.h
@@ -281,6 +281,8 @@
virtual void InitializeInputStateModel();
+ void UpdateTabListObservation(TabListInterface* tab_list);
+
std::unique_ptr<contextual_search::InputStateModel> input_state_model_;
void OnInputStateChanged(const contextual_search::InputState& state);
diff --git a/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_web_contents_helper.cc b/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_web_contents_helper.cc
index 247a6fc..7c9fbcfd 100644
--- a/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_web_contents_helper.cc
+++ b/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_web_contents_helper.cc
@@ -6,6 +6,7 @@
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/location_bar/location_bar.h"
@@ -17,10 +18,9 @@
// on the current browser window, and make it available to the OmniboxPopupUI.
if (BrowserWindowInterface* browser =
chrome::FindBrowserWithTab(web_contents)) {
- set_omnibox_controller(browser->GetBrowserForMigrationOnly()
- ->window()
- ->GetLocationBar()
- ->GetOmniboxController());
+ if (auto* location_bar = browser->GetFeatures().location_bar()) {
+ set_omnibox_controller(location_bar->GetOmniboxController());
+ }
}
}
diff --git a/chrome/browser/ui/webui/searchbox/webui_omnibox_handler.cc b/chrome/browser/ui/webui/searchbox/webui_omnibox_handler.cc
index bae92e8..0ad79fa9 100644
--- a/chrome/browser/ui/webui/searchbox/webui_omnibox_handler.cc
+++ b/chrome/browser/ui/webui/searchbox/webui_omnibox_handler.cc
@@ -14,10 +14,13 @@
#include "chrome/browser/autocomplete/aim_eligibility_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/bookmarks/bookmark_stats.h"
+#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/contextual_search/searchbox_context_data.h"
+#include "chrome/browser/ui/location_bar/location_bar.h"
#include "chrome/browser/ui/omnibox/omnibox_controller.h"
#include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
#include "chrome/browser/ui/omnibox/omnibox_next_features.h"
@@ -31,6 +34,7 @@
#include "chrome/browser/ui/webui/cr_components/searchbox/searchbox_omnibox_client.h"
#include "chrome/browser/ui/webui/metrics_reporter/metrics_reporter.h"
#include "chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.h"
+#include "chrome/browser/ui/webui/omnibox_popup/omnibox_popup_web_contents_helper.h"
#include "chrome/browser/ui/webui/webui_embedding_context.h"
#include "chrome/grit/new_tab_page_resources.h"
#include "components/contextual_search/contextual_search_service.h"
@@ -57,6 +61,7 @@
#include "components/profile_metrics/browser_profile_type.h"
#include "components/search_engines/template_url_service.h"
#include "components/strings/grit/components_strings.h"
+#include "components/tabs/public/tab_interface.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "net/cookies/cookie_util.h"
@@ -130,6 +135,14 @@
base::BindRepeating(&WebuiOmniboxHandler::OnContentSharingPolicyChanged,
base::Unretained(this)));
+ if (tabs::TabInterface* tab =
+ tabs::TabInterface::MaybeGetFromContents(web_ui->GetWebContents())) {
+ tab_will_detach_subscription_ = tab->RegisterWillDetach(base::BindRepeating(
+ &WebuiOmniboxHandler::OnTabWillDetach, base::Unretained(this)));
+ tab_did_insert_subscription_ = tab->RegisterDidInsert(base::BindRepeating(
+ &WebuiOmniboxHandler::OnTabDidInsert, base::Unretained(this)));
+ }
+
OnAimPopupEligibilityChanged();
OnContentSharingPolicyChanged();
}
@@ -391,6 +404,36 @@
ContextualSearchboxHandler::OnActiveTabChanged(tab_list, tab);
}
+void WebuiOmniboxHandler::OnTabWillDetach(
+ tabs::TabInterface* tab,
+ tabs::TabInterface::DetachReason reason) {
+ edit_model_observation_.Reset();
+ autocomplete_controller_observation_.Reset();
+ controller_ = nullptr;
+ UpdateTabListObservation(nullptr);
+}
+
+void WebuiOmniboxHandler::OnTabDidInsert(tabs::TabInterface* tab) {
+ if (auto* browser_window_interface = tab->GetBrowserWindowInterface()) {
+ if (auto* location_bar =
+ browser_window_interface->GetFeatures().location_bar()) {
+ if (auto* omnibox_controller = location_bar->GetOmniboxController()) {
+ edit_model_observation_.Reset();
+ autocomplete_controller_observation_.Reset();
+ controller_ = omnibox_controller;
+ autocomplete_controller_observation_.Observe(autocomplete_controller());
+ edit_model_observation_.Observe(omnibox_controller->edit_model());
+ if (auto* helper = OmniboxPopupWebContentsHelper::FromWebContents(
+ web_contents_.get())) {
+ helper->set_omnibox_controller(omnibox_controller);
+ }
+ UpdateTabListObservation(
+ TabListInterface::From(browser_window_interface));
+ }
+ }
+ }
+}
+
WebuiOmniboxHandler::WebContentsObserver::WebContentsObserver(
WebuiOmniboxHandler* handler,
content::WebContents* web_contents)
diff --git a/chrome/browser/ui/webui/searchbox/webui_omnibox_handler.h b/chrome/browser/ui/webui/searchbox/webui_omnibox_handler.h
index d56cae2..bd5a5d94 100644
--- a/chrome/browser/ui/webui/searchbox/webui_omnibox_handler.h
+++ b/chrome/browser/ui/webui/searchbox/webui_omnibox_handler.h
@@ -92,6 +92,13 @@
tabs::TabInterface* tab) override;
private:
+ // When the omnibox is hosted in a tab, e.g. for debug, it must remain
+ // connected with the host window's OmniboxController. These methods
+ // support disconnect and reconnect as the window changes to avoid UAF.
+ void OnTabWillDetach(tabs::TabInterface* tab,
+ tabs::TabInterface::DetachReason reason);
+ void OnTabDidInsert(tabs::TabInterface* tab);
+
// Delegate to observe WebContents.
// Managed as a separate class to prevent member naming conflicts
// of `web_contents_` with a member of the same name in `SearchboxHandler`.
@@ -123,6 +130,8 @@
PrefChangeRegistrar pref_change_registrar_;
base::CallbackListSubscription aim_eligibility_subscription_;
+ base::CallbackListSubscription tab_will_detach_subscription_;
+ base::CallbackListSubscription tab_did_insert_subscription_;
raw_ptr<MetricsReporter> metrics_reporter_;
Original Bug Report
Heap UAF in WebuiOmniboxHandler
VULNERABILITY DETAILS
The bug is a heap use-after-free that triggers when chrome://omnibox-popup.top-chrome/ is opened as a tab and then moved to a new window. The popup listens to omnibox data from its host window, but when you drag it out, the original window goes empty and gets destroyed, freeing that data without notifying the handler. The next time the moved tab refreshes, closes, or navigates, the cleanup code tries to unregister itself and reads freed memory.
I also tested whether the bug could be reached without loading chrome://omnibox-popup.top-chrome as a tab. For example, by opening the “+” popup (when type something in the address bar) and then closing the window or dragging a tab. Unfortunately those step do not reproduce the crash, the overlay popup widget dismisses synchronously on any focus loss, so the handler is always destroyed while the browser window’s omnibox data is still alive.
VERSION
Chrome Version: 149.0.7792.0 (Developer Build) (64-bit)
Operating System: Ubuntu 24.04
REPRODUCTION CASE
- ./chrome –no-sandbox –enable-features=WebUIOmniboxPopup or ./chrome –no-sandbox –enable-features=WebUIOmniboxAimPopup
- Open
chrome://omnibox-popup.top-chrome/in the first window (Window A). - Open new window (Window B).
- Drag the
chrome://omnibox-popup.top-chrome/tab from Window A’s tab into Window B’s. - In Window B, refresh the
chrome://omnibox-popup.top-chrome/tab.
FOR CRASHES, PLEASE INCLUDE THE FOLLOWING ADDITIONAL INFORMATION
Type of crash: Browser process.
Crash State:
-
asan-s1-uaf.txt = primary scenario, clean heap-use-after-free with complete freed-by and allocated-by stacks.
-
asan-s2-hbo.txt = identical bug after normal user activity between the free and the read, ASAN reclassifies the access as heap-buffer-overflow
Client ID (if relevant): N/A
CREDIT INFORMATION
Reporter credit: gevakun