Medium watch CVSS 7.5 chrome UAF 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
7.5
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in PageInfo
DescriptionUse after free in PageInfo
ComponentPageInfo
Sub-componentPage Info
Bug ClassUAF
Action tierwatch — corruption primitive but gated (uncommon) — not default-reachable
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker446294487
Fix commit90a4060a92d1 (chromium/src) +12/-17
CWECWE-416 (Use-after-free)
CVSS vectorCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedUmar Farooq
Reported2025-09-20 · bounty $2000 (per vendor advisory)
Fix landed2025-10-07 (public git)
Disclosed2025-10-28
Patch gap21 days — fix public in source before the advisory

Background

`PageInfoInfoBarDelegate`
A ConfirmInfoBarDelegate subclass that backs the “reload to apply your updated settings” infobar shown after site settings change in Page Info. It stores the content::ReloadType to use when it triggers a reload.
`infobars::ContentInfoBarManager::AddInfoBar`
Takes ownership of a std::unique_ptr infobar (built by CreateConfirmInfoBar, which itself owns the delegate). From then on the manager controls the delegate’s lifetime.
Ownership transfer with a retained raw pointer
A pattern where code keeps a raw pointer to an object after giving away its unique_ptr. The pointer is only valid for as long as the new owner chooses to keep the object alive.

Root Cause Analysis

Before the patch, PageInfoInfoBarDelegate::Create allocated the delegate with new, wrapped it in a std::unique_ptr<ConfirmInfoBarDelegate>, passed it to infobar_manager->AddInfoBar(CreateConfirmInfoBar(...)), and then returned the raw delegate pointer anyway. The caller in chrome_page_info_delegate.cc (the enclosing function is not named in the hunk) then called delegate->set_reload_type(reload_type) through that raw pointer. Once ownership had passed to the infobar manager, nothing guaranteed the delegate was still alive when Create returned. If AddInfoBar declined to keep the infobar and destroyed it, set_reload_type would write reload_type_ into freed memory (the conditions under which this happens are not in the diff and are inferred).

The fix removes both the returned pointer and the setter. Create now takes content::ReloadType reload_type (default NORMAL) and passes it to a new explicit constructor that initializes reload_type_ before ownership is transferred, so no code touches the delegate after AddInfoBar.

Key insight
The code used a raw pointer to the delegate after giving its unique_ptr to the infobar manager, which may already have destroyed it. The fix sets all of the delegate’s state in its constructor, so nothing needs a pointer to it after the handoff.

Attack Path

  1. Change site settings in Page Info The user opens Page Info and changes a permission or setting so that Chrome decides to offer a reload infobar. This runs the creation branch in chrome_page_info_delegate.cc when a ContentInfoBarManager exists for web_contents_.
  2. Ownership handoff PageInfoInfoBarDelegate::Create hands the new delegate to AddInfoBar inside a unique_ptr and returns its raw pointer.
  3. Infobar not retained Under some condition the manager does not keep the infobar and frees it along with its delegate. The exact condition (for example, infobars being disabled for that tab or a duplicate infobar being rejected) is not shown in the diff and is inferred.
  4. Stale write The caller runs delegate->set_reload_type(reload_type) on the freed delegate, a use-after-free write of a content::ReloadType value in the browser process.

Impact Assessment

The advisory rates this a medium-severity “Use after free in PageInfo”. The freed object lives in the browser process, and the stale access is a single small write of a content::ReloadType enum value, so the attacker has little control over what is written. Turning this into memory corruption beyond that is (inferred). Reaching the bug needs the user to interact with the Page Info UI, plus the timing or state in which the infobar manager drops the newly added infobar. The diff gives no sign that web content alone can drive this path without that user gesture.

Changed Functions

FunctionChangeNotes
if
chrome/browser/ui/page_info/chrome_page_info_delegate.cc
modified

Files Changed

  • chrome/browser/ui/page_info/chrome_page_info_delegate.cc
  • chrome/browser/ui/page_info/page_info_infobar_delegate.cc
  • chrome/browser/ui/page_info/page_info_infobar_delegate.h

Audit Directions

  • Factories that return raw pointers after `AddInfoBar`
    Search for *InfoBarDelegate::Create helpers that call AddInfoBar(CreateConfirmInfoBar(std::unique_ptr<...>(delegate))) and then return or use delegate. Every such use is only safe if AddInfoBar is guaranteed to keep the infobar.
  • Post-construction setters on owned-elsewhere objects
    Look for set_* calls made on a delegate, observer or controller after its unique_ptr has been given to a manager, a views::Widget or a task. Prefer constructor injection, or use the pointer that AddInfoBar returns (and null-check it).
  • Manager APIs that may drop new entries
    Find container or manager Add* methods that can reject and destroy what they are given, and check every caller for the assumption that the object outlives the call.
From 90a4060a92d135f1789056c943cf7e535fa8603b Mon Sep 17 00:00:00 2001
From: Fiona Macintosh <fmacintosh@google.com>
Date: Tue, 07 Oct 2025 09:57:32 -0700
Subject: [PATCH] [Page Info] Fix use-after-free in infobar delegate

Bug: 446294487
Change-Id: Ica9a2077b88c019664b498f03d162802d44c7049
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7008715
Auto-Submit: Fiona Macintosh <fmacintosh@google.com>
Reviewed-by: Christian Dullweber <dullweber@chromium.org>
Commit-Queue: Fiona Macintosh <fmacintosh@google.com>
Cr-Commit-Position: refs/heads/main@{#1526366}
---

diff --git a/chrome/browser/ui/page_info/chrome_page_info_delegate.cc b/chrome/browser/ui/page_info/chrome_page_info_delegate.cc
index ff61c81e..a8cbccb 100644
--- a/chrome/browser/ui/page_info/chrome_page_info_delegate.cc
+++ b/chrome/browser/ui/page_info/chrome_page_info_delegate.cc
@@ -225,8 +225,7 @@
   infobars::ContentInfoBarManager* infobar_manager =
       infobars::ContentInfoBarManager::FromWebContents(web_contents_);
   if (infobar_manager) {
-    auto* delegate = PageInfoInfoBarDelegate::Create(infobar_manager);
-    delegate->set_reload_type(reload_type);
+    PageInfoInfoBarDelegate::Create(infobar_manager, reload_type);
     return true;
   }
   return false;
diff --git a/chrome/browser/ui/page_info/page_info_infobar_delegate.cc b/chrome/browser/ui/page_info/page_info_infobar_delegate.cc
index 54deb3c5..f3abf4f 100644
--- a/chrome/browser/ui/page_info/page_info_infobar_delegate.cc
+++ b/chrome/browser/ui/page_info/page_info_infobar_delegate.cc
@@ -18,16 +18,14 @@
 #include "ui/base/l10n/l10n_util.h"
 
 // static
-PageInfoInfoBarDelegate* PageInfoInfoBarDelegate::Create(
-    infobars::ContentInfoBarManager* infobar_manager) {
-  auto* delegate = new PageInfoInfoBarDelegate();
+void PageInfoInfoBarDelegate::Create(
+    infobars::ContentInfoBarManager* infobar_manager,
+    content::ReloadType reload_type) {
   infobar_manager->AddInfoBar(
-      CreateConfirmInfoBar(std::unique_ptr<ConfirmInfoBarDelegate>(delegate)));
-  return delegate;
+      CreateConfirmInfoBar(std::unique_ptr<ConfirmInfoBarDelegate>(
+          new PageInfoInfoBarDelegate(reload_type))));
 }
 
-PageInfoInfoBarDelegate::PageInfoInfoBarDelegate() = default;
-
 PageInfoInfoBarDelegate::~PageInfoInfoBarDelegate() = default;
 
 infobars::InfoBarDelegate::InfoBarIdentifier
diff --git a/chrome/browser/ui/page_info/page_info_infobar_delegate.h b/chrome/browser/ui/page_info/page_info_infobar_delegate.h
index 0727256..ba95e10d 100644
--- a/chrome/browser/ui/page_info/page_info_infobar_delegate.h
+++ b/chrome/browser/ui/page_info/page_info_infobar_delegate.h
@@ -24,15 +24,13 @@
 
   // Creates a page info infobar and delegate and adds the infobar to
   // |infobar_manager|.
-  static PageInfoInfoBarDelegate* Create(
-      infobars::ContentInfoBarManager* infobar_manager);
-
-  void set_reload_type(content::ReloadType reload_type) {
-    reload_type_ = reload_type;
-  }
+  static void Create(
+      infobars::ContentInfoBarManager* infobar_manager,
+      content::ReloadType reload_type = content::ReloadType::NORMAL);
 
  private:
-  PageInfoInfoBarDelegate();
+  explicit PageInfoInfoBarDelegate(content::ReloadType reload_type)
+      : reload_type_(reload_type) {}
   ~PageInfoInfoBarDelegate() override;
 
   // ConfirmInfoBarDelegate:
@@ -44,7 +42,7 @@
   bool Accept() override;
 
   // The type of reload the info bar should trigger when closed.
-  content::ReloadType reload_type_ = content::ReloadType::NORMAL;
+  content::ReloadType reload_type_;
 };
 
 #endif  // CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_INFOBAR_DELEGATE_H_
Loading diff…

Original Bug Report

reported by pu...@gmail.com

heap-use-after-free C:\b\s\w\ir\cache\builder\src\chrome\browser\ui\page_info\page_info_infobar_dele

Steps to reproduce the problem

  1. i will be updating soon

Problem Description

================================================================= ==11072==ERROR: AddressSanitizer: heap-use-after-free on address 0x11f90ac4a4f0 at pc 0x7ffdc8b6a9fc bp 0x0021f1ffab70 sp 0x0021f1ffabb8 WRITE of size 4 at 0x11f90ac4a4f0 thread T0 #0 0x7ffdc8b6a9fb in PageInfoInfoBarDelegate::set_reload_type C:\b\s\w\ir\cache\builder\src\chrome\browser\ui\page_info\page_info_infobar_delegate.h:31 #1 0x7ffdc8b6a9fb in ChromePageInfoDelegate::CreateInfoBarDelegate(enum content::ReloadType) C:\b\s\w\ir\cache\builder\src\chrome\browser\ui\page_info\chrome_page_info_delegate.cc:226:15 #2 0x7ffde101ffb0 in PageInfo::OnUIClosing(bool ) C:\b\s\w\ir\cache\builder\src\components\page_info\page_info.cc:796:20 #3 0x7ffdc94f5841 in PageInfoBubbleView::OnWidgetDestroying(class views::Widget ) C:\b\s\w\ir\cache\builder\src\chrome\browser\ui\views\page_info\page_info_bubble_view.cc:352:17 #4 0x7ffdcaecbb91 in std::__Cr::__invoke C:\b\s\w\ir\cache\builder\src\third_party\libc++\src\include__type_traits\invoke.h:203 #5 0x7ffdcaecbb91 in std::__Cr::invoke C:\b\s\w\ir\cache\builder\src\third_party\libc++\src\include__functional\invoke.h:29 #6 0x7ffdcaecbb91 in base::ObserverList<class views::WidgetObserver, 0, 1, class base::internal::CheckedObserverAdapter>::Notify<void (__cdecl views::WidgetObserver::)(class views::Widget ), class views::Widget >(void (__cdecl views::WidgetObserver::)(class views::Widget ), class views::Widget const &) C:\b\s\w\ir\cache\builder\src\base\observer_list.h:398:7 #7 0x7ffdcaec04ab in views::Widget::HandleWidgetDestroying(void) C:\b\s\w\ir\cache\builder\src\ui\views\widget\widget.cc:2719:14 #8 0x7ffdcadeff52 in views::DesktopWindowTreeHostWin::HandleDestroying(void) C:\b\s\w\ir\cache\builder\src\ui\views\widget\desktop_aura\desktop_window_tree_host_win.cc:1052:30 #9 0x7ffdcae80324 in views::HWNDMessageHandler::OnDestroy(void) C:\b\s\w\ir\cache\builder\src\ui\views\win\hwnd_message_handler.cc:1891:14 #10 0x7ffdcae74182 in views::HWNDMessageHandler::ProcessWindowMessage(struct HWND_, unsigned int, unsigned __int64, __int64, __int64 &, unsigned long) C:\b\s\w\ir\cache\builder\src\ui\views\win\hwnd_message_handler.h:468:5 #11 0x7ffdcae7151d in views::HWNDMessageHandler::OnWndProc(unsigned int, unsigned __int64, int64) C:\b\s\w\ir\cache\builder\src\ui\views\win\hwnd_message_handler.cc:1178:7 #12 0x7ffdcf592d7c in gfx::WindowImpl::WndProc(struct HWND, unsigned int, unsigned __int64, int64) C:\b\s\w\ir\cache\builder\src\ui\gfx\win\window_impl.cc:313:18 #13 0x7ffdcf59185e in base::win::WrappedWindowProc<&gfx::WindowImpl::WndProc(struct HWND, unsigned int, unsigned __int64, int64)>(struct HWND, unsigned int, unsigned __int64, __int64) C:\b\s\w\ir\cache\builder\src\base\win\wrapped_window_proc.h:74:10 #14 0x7ffedc787cf5 (C:\WINDOWS\System32\USER32.dll+0x180017cf5) #15 0x7ffedc78757b (C:\WINDOWS\System32\USER32.dll+0x18001757b) #16 0x7ffedc7b8562 (C:\WINDOWS\System32\USER32.dll+0x180048562) #17 0x7ffeddb47253 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x180167253) #18 0x7ffedb182543 (C:\WINDOWS\System32\win32u.dll+0x180002543) #19 0x7ffdcae8c07f in base::internal::DecayedFunctorTraits<void (HWNDMessageHandler::)(),base::WeakPtrviews::HWNDMessageHandler &&>::Invoke C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:731 #20 0x7ffdcae8c07f in base::internal::InvokeHelper<1,base::internal::FunctorTraits<void (HWNDMessageHandler::&&)(),base::WeakPtrviews::HWNDMessageHandler &&>,void,0>::MakeItSo C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:947 #21 0x7ffdcae8c07f in base::internal::Invoker<base::internal::FunctorTraits<void (HWNDMessageHandler::&&)(),base::WeakPtrviews::HWNDMessageHandler &&>,base::internal::BindState<1,1,0,void (HWNDMessageHandler::)(),base::WeakPtrviews::HWNDMessageHandler >,void ()>::RunImpl C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:1060 #22 0x7ffdcae8c07f in base::internal::Invoker<struct base::internal::FunctorTraits<void (__cdecl views::HWNDMessageHandler::&&)(void), class base::WeakPtr<class views::HWNDMessageHandler> &&>, struct base::internal::BindState<1, 1, 0, void (__cdecl views::HWNDMessageHandler::)(void), class base::WeakPtr<class views::HWNDMessageHandler>>, (void)>::RunOnce(class base::internal::BindStateBase *) C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:973:12 #23 0x7ffdcc859cb3 in base::OnceCallback<void ()>::Run C:\b\s\w\ir\cache\builder\src\base\functional\callback.h:156 #24 0x7ffdcc859cb3 in base::TaskAnnotator::RunTaskImpl(struct base::PendingTask &) C:\b\s\w\ir\cache\builder\src\base\task\common\task_annotator.cc:207:34 #25 0x7ffdcc82ceb9 in base::TaskAnnotator::RunTask C:\b\s\w\ir\cache\builder\src\base\task\common\task_annotator.h:104 #26 0x7ffdcc82ceb9 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(class base::LazyNow *) C:\b\s\

Summary

heap-use-after-free C:\b\s\w\ir\cache\builder\src\chrome\browser\ui\page_info\page_info_infobar_dele

Custom Questions

Reporter credit:

Puf

Additional Data

Category: Security
Chrome Channel: Not sure
Regression: N/A \

View on issue tracker
Uploaded PoC files