Chrome · Google Lens
CVE-2026-11248
Logic Error in Google Lens
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Files Changed
chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.ccchrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h
Patch
From a62e933a74e07e39629e366000d1fde315f5b63c Mon Sep 17 00:00:00 2001
From: Duncan Mercer <mercerd@google.com>
Date: Tue, 14 Apr 2026 10:07:29 -0700
Subject: [PATCH] [Lens] Fix Side Panel CSRF and context dropping
Preserve initiator context when redirecting side panel navigations to the main browser tab or new tabs.
Replaced insecure OpenGURL usage with constructs from NavigationHandle.
Cleared frame_tree_node_id to prevent ownership safety check crashes.
Bug: 497946941
Change-Id: I05b87bf322d873408bcf13d7a5caa6c328a27049
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7729157
Commit-Queue: Duncan Mercer <mercerd@google.com>
Reviewed-by: Charlie Reis <creis@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1614565}
---
diff --git a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc
index 3cc4c84c..cbb8d10 100644
--- a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc
+++ b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc
@@ -49,6 +49,7 @@
#include "content/public/browser/media_session.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/referrer.h"
#include "net/base/net_errors.h"
@@ -231,7 +232,8 @@
}
bool LensOverlaySidePanelCoordinator::MaybeHandleTextDirectives(
- const GURL& nav_url) {
+ content::NavigationHandle* navigation_handle) {
+ const GURL& nav_url = navigation_handle->GetURL();
if (ShouldHandleTextDirectives(nav_url)) {
const GURL& page_url = lens_search_controller_->GetTabInterface()
->GetContents()
@@ -249,9 +251,15 @@
page_url_text_query != nav_url_text_query) {
lens::RecordHandleTextDirectiveResult(
lens::LensOverlayTextDirectiveResult::kOpenedInNewTab);
+ // Preserve security-relevant initiator information from the original
+ // navigation.
+ content::OpenURLParams params =
+ content::OpenURLParams::FromNavigationHandle(navigation_handle);
+ params.frame_tree_node_id = content::FrameTreeNodeId();
+ params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
lens_search_controller_->GetTabInterface()
->GetBrowserWindowInterface()
- ->OpenGURL(nav_url, WindowOpenDisposition::NEW_FOREGROUND_TAB);
+ ->OpenURL(params, /*navigation_handle_callback=*/{});
return true;
}
}
@@ -266,11 +274,18 @@
->GetPrimaryPage();
companion::TextFinderManager* text_finder_manager =
companion::TextFinderManager::GetOrCreateForPage(page);
+ // Preserve security-relevant initiator information from the original
+ // navigation.
+ content::OpenURLParams params =
+ content::OpenURLParams::FromNavigationHandle(navigation_handle);
+ params.frame_tree_node_id = content::FrameTreeNodeId();
+ params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
+
text_finder_manager->CreateTextFinders(
text_fragments,
base::BindOnce(
&LensOverlaySidePanelCoordinator::OnTextFinderLookupComplete,
- weak_ptr_factory_.GetWeakPtr(), nav_url));
+ weak_ptr_factory_.GetWeakPtr(), std::move(params)));
return true;
}
return false;
@@ -835,21 +850,16 @@
return;
}
- // This navigation is created from this component, so we consider it to be
- // browser initiated. In particular, we do not plumb all the parameters from
- // the original navigation. For instance we do not populate the
- // `initiator_frame_token`. This means some security properties like sandbox
- // flags are lost along the way.
- //
- // This is not problematic because we trust the original navigation was
- // initiated from the expected origin.
- //
- // Specifically, we need the navigation to be considered browser-initiated, as
- // renderer-initiated navigation history entries may be skipped if the
- // document does not receive any user interaction (like in our case). See
- // https://issuetracker.google.com/285038653
+ // This navigation is created from this component to open a link in a new tab.
+ // We use the `renderer_initiated` value from the source navigation and plumb
+ // the `initiator_origin`, `initiator_frame_token`, and `initiator_process_id`
+ // to preserve security properties (like sandbox flags).
content::OpenURLParams params(url, referrer, disposition, transition,
- /*is_renderer_initiated=*/false);
+ renderer_initiated);
+ params.initiator_origin = source_render_frame_host->GetLastCommittedOrigin();
+ params.initiator_frame_token = source_render_frame_host->GetFrameToken();
+ params.initiator_process_id =
+ source_render_frame_host->GetProcess()->GetID().GetUnsafeValue();
// We can't open a new tab while the observer is running because it might
// destroy this WebContents. Post as task instead.
@@ -903,7 +913,7 @@
// If the contextual search box is enabled, cross-origin navigations could
// be a citation that should be rendered as text highlights in the current
// tab.
- if (MaybeHandleTextDirectives(nav_url)) {
+ if (MaybeHandleTextDirectives(navigation_handle)) {
return;
}
@@ -913,9 +923,15 @@
return;
}
+ // Preserve security-relevant initiator information from the original
+ // navigation.
+ content::OpenURLParams params =
+ content::OpenURLParams::FromNavigationHandle(navigation_handle);
+ params.frame_tree_node_id = content::FrameTreeNodeId();
+ params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
lens_search_controller_->GetTabInterface()
->GetBrowserWindowInterface()
- ->OpenGURL(nav_url, WindowOpenDisposition::NEW_FOREGROUND_TAB);
+ ->OpenURL(params, /*navigation_handle_callback=*/{});
return;
}
@@ -924,9 +940,15 @@
->GetBrowserWindowInterface()
->GetProfile();
if (ShouldOpenSearchURLInNewTab(nav_url, lens::IsAimM3Enabled(profile))) {
+ // Preserve security-relevant initiator information from the original
+ // navigation.
+ content::OpenURLParams params =
+ content::OpenURLParams::FromNavigationHandle(navigation_handle);
+ params.frame_tree_node_id = content::FrameTreeNodeId();
+ params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
lens_search_controller_->GetTabInterface()
->GetBrowserWindowInterface()
- ->OpenGURL(nav_url, WindowOpenDisposition::NEW_FOREGROUND_TAB);
+ ->OpenURL(params, /*navigation_handle_callback=*/{});
return;
}
@@ -1052,8 +1074,9 @@
}
void LensOverlaySidePanelCoordinator::OnTextFinderLookupComplete(
- const GURL& nav_url,
+ const content::OpenURLParams& params,
const std::vector<std::pair<std::string, bool>>& lookup_results) {
+ const GURL& nav_url = params.url;
const GURL& page_url = lens_search_controller_->GetTabInterface()
->GetContents()
->GetLastCommittedURL();
@@ -1071,7 +1094,7 @@
lens::LensOverlayTextDirectiveResult::kOpenedInNewTab);
lens_search_controller_->GetTabInterface()
->GetBrowserWindowInterface()
- ->OpenGURL(nav_url, WindowOpenDisposition::NEW_FOREGROUND_TAB);
+ ->OpenURL(params, /*navigation_handle_callback=*/{});
return;
}
@@ -1092,7 +1115,7 @@
lens::LensOverlayTextDirectiveResult::kOpenedInNewTab);
lens_search_controller_->GetTabInterface()
->GetBrowserWindowInterface()
- ->OpenGURL(nav_url, WindowOpenDisposition::NEW_FOREGROUND_TAB);
+ ->OpenURL(params, /*navigation_handle_callback=*/{});
return;
}
text_directives.push_back(pair.first);
diff --git a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h
index cab633d5..142db9b 100644
--- a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h
+++ b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h
@@ -146,9 +146,9 @@
// Handles rendering text highlights on the main browser window based on
// navigations from the side panel. Returns true if handled, false otherwise.
- // `nav_url` refers to the URL that the side panel was set to navigate to. It
- // is compared to the URL of the current open tab.
- bool MaybeHandleTextDirectives(const GURL& nav_url);
+ // The URL is extracted from the `navigation_handle` and compared to the URL
+ // of the current open tab.
+ bool MaybeHandleTextDirectives(content::NavigationHandle* navigation_handle);
// Handles seeking videos on the main browser window based on navigations from
// the side panel. Returns true if handled, false otherwise. `nav_url` refers
@@ -345,9 +345,9 @@
// Callback for when the `text_finder` identifies the provided text directives
// on the page. If all the directives were found, then this function will
// create highlights on the page for each. Otherwise, it will open the
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page