Low chrome Logic Error 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactImproper input validation in NTP Footer
DescriptionImproper input validation in NTP Footer
ComponentNTP Footer
Bug ClassLogic Error
Tracker517395590
Fix commit3bad81ace4d4 (chromium/src) +109/-4
CISA KEVNot listed
CreditedOrange Tsai (@orange_8361) of DEVCORE Research Team
Disclosed2026-08-25

Changed Functions

FunctionChangeNotes
if
chrome/browser/ui/views/new_tab_footer/footer_controller.cc
modified
IN_PROC_BROWSER_TEST_F
chrome/browser/ui/views/new_tab_footer/footer_controller_browsertest.cc
modified
if
chrome/browser/ui/views/new_tab_footer/footer_web_view.cc
modified

Files Changed

  • chrome/browser/ui/views/new_tab_footer/footer_controller.cc
  • chrome/browser/ui/views/new_tab_footer/footer_controller_browsertest.cc
  • chrome/browser/ui/views/new_tab_footer/footer_web_view.cc
  • chrome/browser/ui/views/new_tab_footer/footer_web_view.h
  • chrome/browser/ui/webui/new_tab_footer/BUILD.gn
  • chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler.cc
  • chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc
From 3bad81ace4d4d6d740b724cb56f47c4b414e05fa Mon Sep 17 00:00:00 2001
From: Paul Adedeji <pauladedeji@google.com>
Date: Mon, 06 Jul 2026 17:24:38 -0700
Subject: [PATCH] [ntp footer] Ensure proper navigation context attribution.

Passes explicit source `WebContents` parameters during
`OpenUrlInCurrentTab` navigations from the NTP footer WebUI. This
ensures navigations are properly associated with their attached tab
context.

Change-Id: Idaf35b2b6e120a0303b6e8190bdf53882ba5297a
Bug: b:517395590
Fixed: b:517395590
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8025870
Auto-Submit: Paul Adedeji <pauladedeji@google.com>
Commit-Queue: Riley Tatum <rtatum@google.com>
Reviewed-by: Riley Tatum <rtatum@google.com>
Cr-Commit-Position: refs/heads/main@{#1657594}
---

diff --git a/chrome/browser/ui/views/new_tab_footer/footer_controller.cc b/chrome/browser/ui/views/new_tab_footer/footer_controller.cc
index 6bd39ba..89951e2 100644
--- a/chrome/browser/ui/views/new_tab_footer/footer_controller.cc
+++ b/chrome/browser/ui/views/new_tab_footer/footer_controller.cc
@@ -145,7 +145,7 @@
   const bool show_extension = ShouldShowExtensionFooter(url);
   const bool show = show_managed || show_extension;
   if (show) {
-    footer_->ShowUI(load_start_timestamp, url);
+    footer_->ShowUI(load_start_timestamp, url, web_contents()->GetWeakPtr());
   } else {
     footer_->CloseUI();
   }
diff --git a/chrome/browser/ui/views/new_tab_footer/footer_controller_browsertest.cc b/chrome/browser/ui/views/new_tab_footer/footer_controller_browsertest.cc
index be73949b..486728db 100644
--- a/chrome/browser/ui/views/new_tab_footer/footer_controller_browsertest.cc
+++ b/chrome/browser/ui/views/new_tab_footer/footer_controller_browsertest.cc
@@ -30,6 +30,7 @@
 #include "components/search/ntp_features.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
 #include "extensions/common/extension.h"
 #include "extensions/test/test_extension_dir.h"
 #include "net/base/url_util.h"
@@ -467,3 +468,34 @@
              TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB);
   EXPECT_FALSE(footer()->GetVisible());
 }
+
+IN_PROC_BROWSER_TEST_F(FooterControllerSplitViewTest, OpenUrlFromTabInSplit) {
+  auto extension = LoadNtpExtension();
+
+  tab_strip_model()->ActivateTabAt(0);
+  NavigateCurrentTab(GURL(extension->url()));
+  content::WebContents* ntp_tab_contents =
+      tab_strip_model()->GetWebContentsAt(0);
+
+  tab_strip_model()->ActivateTabAt(1);
+  content::WebContents* active_tab_contents =
+      tab_strip_model()->GetActiveWebContents();
+  ASSERT_NE(ntp_tab_contents, active_tab_contents);
+
+  auto* ntp_container = BrowserView::GetBrowserViewForBrowser(browser())
+                            ->GetContentsContainerViewFor(ntp_tab_contents);
+  ASSERT_TRUE(ntp_container);
+  auto* ntp_footer = ntp_container->new_tab_footer_view();
+  ASSERT_TRUE(ntp_footer);
+
+  const GURL kTargetUrl("https://www.google.com/");
+  content::OpenURLParams params(kTargetUrl, content::Referrer(),
+                                WindowOpenDisposition::CURRENT_TAB,
+                                ui::PAGE_TRANSITION_LINK, false);
+  content::TestNavigationObserver nav_observer(ntp_tab_contents);
+  ntp_footer->OpenURLFromTab(ntp_footer->GetWebContents(), params, {});
+  nav_observer.Wait();
+
+  EXPECT_EQ(kTargetUrl, ntp_tab_contents->GetLastCommittedURL());
+  EXPECT_EQ(GURL(kNonNtpUrl), active_tab_contents->GetLastCommittedURL());
+}
diff --git a/chrome/browser/ui/views/new_tab_footer/footer_web_view.cc b/chrome/browser/ui/views/new_tab_footer/footer_web_view.cc
index b43be1c..15246ae 100644
--- a/chrome/browser/ui/views/new_tab_footer/footer_web_view.cc
+++ b/chrome/browser/ui/views/new_tab_footer/footer_web_view.cc
@@ -33,8 +33,12 @@
   contents_wrapper_ = nullptr;
 }
 
-void NewTabFooterWebView::ShowUI(base::TimeTicks load_start, GURL url) {
+void NewTabFooterWebView::ShowUI(
+    base::TimeTicks load_start,
+    GURL url,
+    base::WeakPtr<content::WebContents> attached_tab_contents) {
   attached_tab_url_ = url;
+  attached_tab_contents_ = attached_tab_contents;
   ShowUI();
   base::UmaHistogramMediumTimes("NewTabPage.Footer.ShownTime",
                                 base::TimeTicks::Now() - load_start);
@@ -100,6 +104,18 @@
       event, GetFocusManager());
 }
 
+content::WebContents* NewTabFooterWebView::OpenURLFromTab(
+    content::WebContents* source,
+    const content::OpenURLParams& params,
+    base::OnceCallback<void(content::NavigationHandle&)>
+        navigation_handle_callback) {
+  if (!attached_tab_contents_) {
+    return nullptr;
+  }
+  return attached_tab_contents_->OpenURL(params,
+                                         std::move(navigation_handle_callback));
+}
+
 BEGIN_METADATA(NewTabFooterWebView)
 END_METADATA
 
diff --git a/chrome/browser/ui/views/new_tab_footer/footer_web_view.h b/chrome/browser/ui/views/new_tab_footer/footer_web_view.h
index 8b762ba..78bcf66 100644
--- a/chrome/browser/ui/views/new_tab_footer/footer_web_view.h
+++ b/chrome/browser/ui/views/new_tab_footer/footer_web_view.h
@@ -38,7 +38,9 @@
   NewTabFooterWebView& operator=(const NewTabFooterWebView&) = delete;
   ~NewTabFooterWebView() override;
 
-  void ShowUI(base::TimeTicks load_start, GURL url);
+  void ShowUI(base::TimeTicks load_start,
+              GURL url,
+              base::WeakPtr<content::WebContents> attached_tab_contents);
 
   // WebUIContentsWrapper::Host:
   void ShowUI() override;
@@ -49,12 +51,18 @@
   void HideCustomContextMenu() override;
   bool HandleKeyboardEvent(content::WebContents* source,
                            const input::NativeWebKeyboardEvent& event) override;
+  content::WebContents* OpenURLFromTab(
+      content::WebContents* source,
+      const content::OpenURLParams& params,
+      base::OnceCallback<void(content::NavigationHandle&)>
+          navigation_handle_callback) override;
 
  private:
   // The URL of tab that the footer is attached to.
   // This URL is updated on navigation or tab change when the footer needs to be
   // shown.
   GURL attached_tab_url_;
+  base::WeakPtr<content::WebContents> attached_tab_contents_;
   std::unique_ptr<views::MenuRunner> context_menu_runner_;
   std::unique_ptr<ui::MenuModel> context_menu_model_;
   // Processes keyboard events not handled by the renderer.
diff --git a/chrome/browser/ui/webui/new_tab_footer/BUILD.gn b/chrome/browser/ui/webui/new_tab_footer/BUILD.gn
index d58eaad..1d980eca 100644
--- a/chrome/browser/ui/webui/new_tab_footer/BUILD.gn
+++ b/chrome/browser/ui/webui/new_tab_footer/BUILD.gn
@@ -101,6 +101,7 @@
   deps = [
     ":test_support",
     "//chrome/browser/enterprise/browser_management:management_identity",
+    "//chrome/browser/ui/webui:webui_util",
     "//components/themes",
   ]
 }
diff --git a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler.cc b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler.cc
index e007288..0bf13c0 100644
--- a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler.cc
+++ b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler.cc
@@ -184,7 +184,7 @@
   content::OpenURLParams params(url, content::Referrer(),
                                 WindowOpenDisposition::CURRENT_TAB,
                                 ui::PAGE_TRANSITION_LINK, false);
-  browser_window->OpenURL(params, /*navigation_handle_callback=*/{});
+  web_contents_->OpenURL(params, /*navigation_handle_callback=*/{});
 }
 
 std::string NewTabFooterHandler::GetManagementNoticeText() {
diff --git a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc
index 3d8efbe06..1ae6537 100644
--- a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc
+++ b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc
@@ -14,13 +14,16 @@
 #include "chrome/browser/extensions/extension_url_overrides.h"
 #include "chrome/browser/search/background/ntp_custom_background_service.h"
 #include "chrome/browser/search/background/ntp_custom_background_service_factory.h"
+#include "chrome/browser/ui/browser_window/test/mock_browser_window_interface.h"
 #include "chrome/browser/ui/webui/new_tab_footer/mock_new_tab_footer_document.h"
 #include "chrome/browser/ui/webui/new_tab_footer/new_tab_footer.mojom.h"
 #include "chrome/browser/ui/webui/top_chrome/top_chrome_web_ui_controller.h"
+#include "chrome/browser/ui/webui/webui_embedding_context.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/themes/ntp_custom_background_service_observer.h"
+#include "content/public/browser/web_contents_delegate.h"
 #include "content/public/test/test_web_ui.h"
 #include "extensions/browser/extension_registrar.h"
 #include "extensions/browser/test_extension_registry_observer.h"
@@ -73,6 +76,17 @@
   MOCK_METHOD(void, AddObserver, (NtpCustomBackgroundServiceObserver*));
 };
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/chrome/browser/ui/views/new_tab_footer/footer_controller_browsertest.cc b/chrome/browser/ui/views/new_tab_footer/footer_controller_browsertest.cc
index be73949b..486728db 100644
--- a/chrome/browser/ui/views/new_tab_footer/footer_controller_browsertest.cc
+++ b/chrome/browser/ui/views/new_tab_footer/footer_controller_browsertest.cc
@@ -30,6 +30,7 @@
 #include "components/search/ntp_features.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
 #include "extensions/common/extension.h"
 #include "extensions/test/test_extension_dir.h"
 #include "net/base/url_util.h"
@@ -467,3 +468,34 @@
              TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB);
   EXPECT_FALSE(footer()->GetVisible());
 }
+
+IN_PROC_BROWSER_TEST_F(FooterControllerSplitViewTest, OpenUrlFromTabInSplit) {
+  auto extension = LoadNtpExtension();
+
+  tab_strip_model()->ActivateTabAt(0);
+  NavigateCurrentTab(GURL(extension->url()));
+  content::WebContents* ntp_tab_contents =
+      tab_strip_model()->GetWebContentsAt(0);
+
+  tab_strip_model()->ActivateTabAt(1);
+  content::WebContents* active_tab_contents =
+      tab_strip_model()->GetActiveWebContents();
+  ASSERT_NE(ntp_tab_contents, active_tab_contents);
+
+  auto* ntp_container = BrowserView::GetBrowserViewForBrowser(browser())
+                            ->GetContentsContainerViewFor(ntp_tab_contents);
+  ASSERT_TRUE(ntp_container);
+  auto* ntp_footer = ntp_container->new_tab_footer_view();
+  ASSERT_TRUE(ntp_footer);
+
+  const GURL kTargetUrl("https://www.google.com/");
+  content::OpenURLParams params(kTargetUrl, content::Referrer(),
+                                WindowOpenDisposition::CURRENT_TAB,
+                                ui::PAGE_TRANSITION_LINK, false);
+  content::TestNavigationObserver nav_observer(ntp_tab_contents);
+  ntp_footer->OpenURLFromTab(ntp_footer->GetWebContents(), params, {});
+  nav_observer.Wait();
+
+  EXPECT_EQ(kTargetUrl, ntp_tab_contents->GetLastCommittedURL());
+  EXPECT_EQ(GURL(kNonNtpUrl), active_tab_contents->GetLastCommittedURL());
+}
diff --git a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc
index 3d8efbe06..1ae6537 100644
--- a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc
+++ b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc
@@ -14,13 +14,16 @@
 #include "chrome/browser/extensions/extension_url_overrides.h"
 #include "chrome/browser/search/background/ntp_custom_background_service.h"
 #include "chrome/browser/search/background/ntp_custom_background_service_factory.h"
+#include "chrome/browser/ui/browser_window/test/mock_browser_window_interface.h"
 #include "chrome/browser/ui/webui/new_tab_footer/mock_new_tab_footer_document.h"
 #include "chrome/browser/ui/webui/new_tab_footer/new_tab_footer.mojom.h"
 #include "chrome/browser/ui/webui/top_chrome/top_chrome_web_ui_controller.h"
+#include "chrome/browser/ui/webui/webui_embedding_context.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/themes/ntp_custom_background_service_observer.h"
+#include "content/public/browser/web_contents_delegate.h"
 #include "content/public/test/test_web_ui.h"
 #include "extensions/browser/extension_registrar.h"
 #include "extensions/browser/test_extension_registry_observer.h"
@@ -73,6 +76,17 @@
   MOCK_METHOD(void, AddObserver, (NtpCustomBackgroundServiceObserver*));
 };
 
+class MockWebContentsDelegate : public content::WebContentsDelegate {
+ public:
+  MOCK_METHOD(content::WebContents*,
+              OpenURLFromTab,
+              (content::WebContents * source,
+               const content::OpenURLParams& params,
+               base::OnceCallback<void(content::NavigationHandle&)>
+                   navigation_handle_callback),
+              (override));
+};
+
 class NewTabFooterHandlerExtensionTest
     : public extensions::ExtensionServiceTestBase {
  public:
@@ -282,6 +296,40 @@
   testing::Mock::VerifyAndClearExpectations(&document_);
 }
 
+TEST_F(NewTabFooterHandlerExtensionTest, OpenUrlInCurrentTab) {
+  testing::NiceMock<MockBrowserWindowInterface> mock_browser_interface;
+  webui::SetBrowserWindowInterface(web_contents_.get(),
+                                   &mock_browser_interface);
+
+  MockWebContentsDelegate mock_delegate;
+  web_contents_->SetDelegate(&mock_delegate);
+
+  const GURL kTestUrl("https://www.example.com");
+  EXPECT_CALL(
+      mock_delegate,
+      OpenURLFromTab(web_contents_.get(),
+                     testing::Field(&content::OpenURLParams::url, kTestUrl),
+                     testing::_))
+      .WillOnce(testing::Return(nullptr));
+
+  handler().OpenUrlInCurrentTab(kTestUrl);
+}
+
+TEST_F(NewTabFooterHandlerExtensionTest, OpenUrlInCurrentTab_InvalidUrl) {
+  testing::NiceMock<MockBrowserWindowInterface> mock_browser_interface;
+  webui::SetBrowserWindowInterface(web_contents_.get(),
+                                   &mock_browser_interface);
+
+  MockWebContentsDelegate mock_delegate;
+  web_contents_->SetDelegate(&mock_delegate);
+
+  const GURL kInvalidUrl("https://");
+  EXPECT_CALL(mock_delegate, OpenURLFromTab(testing::_, testing::_, testing::_))
+      .Times(0);
+
+  handler().OpenUrlInCurrentTab(kInvalidUrl);
+}
+
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
 class NewTabFooterHandlerEnterpriseTest : public testing::Test {
  public:
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.