Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Read Anything
DescriptionUse after free in Read Anything
ComponentRead Anything
Bug ClassUAF
Tracker517607902
Fix commitfcc4a00e3a9a (chromium/src) +1/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-08

Files Changed

  • chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
From fcc4a00e3a9a8c0bc6bedfe4beeb4120ead611df Mon Sep 17 00:00:00 2001
From: Lauren Winston <lwinston@google.com>
Date: Mon, 01 Jun 2026 11:54:01 -0700
Subject: [PATCH] Clean up audio state in #WebContentsDestroyed

Fixed:517607902

Change-Id: I005e24b372ac73e91c9bcc1c8f973699263a7e1c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7881344
Reviewed-by: Eitan Goldberger <eitang@google.com>
Commit-Queue: Lauren Winston <lwinston@google.com>
Cr-Commit-Position: refs/heads/main@{#1639561}
---

diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
index 48171adf..dd30b0dc 100644
--- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
+++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
@@ -553,6 +553,7 @@
 
 void ReadAnythingUntrustedPageHandler::WebContentsDestroyed() {
   translate_observation_.Reset();
+  audible_closure_.RunAndReset();
 }
 
 void ReadAnythingUntrustedPageHandler::AccessibilityEventReceived(
Loading diff…

Original Bug Report

reported by vm...@google.com

Browser Process Use-After-Free in ReadAnythingUntrustedPageHandler via MarkAudible

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. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: A potential Use-After-Free (UAF) vulnerability exists in the browser process due to a lifecycle mismatch in ReadAnythingUntrustedPageHandler. When the Reading Mode side panel registers a tab as audible, it receives a closure wrapping a raw pointer to AudioStreamMonitor which can be triggered after the tab’s destruction.

Affected files:

  • chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc

Estimated timestamp from git blame: 2025-05-30

Description

A potential Use-After-Free (UAF) vulnerability exists in the highly privileged Browser process of Chromium. The issue occurs within the lifecycle management of ReadAnythingUntrustedPageHandler when updating the audibility status of observed tabs.

When a compromised sandboxed renderer sends the Mojo message OnReadAloudAudioStateChange(true) to the browser, the handler invokes WebContentsImpl::MarkAudible(), which registers a client on the tab’s AudioStreamMonitor and returns a base::ScopedClosureRunner stored in audible_closure_. This closure holds a raw/un-managed pointer to the AudioStreamMonitor (which is an inline member of the observed WebContentsImpl).

If the observed tab is closed and destroyed, the AudioStreamMonitor is freed. However, ReadAnythingUntrustedPageHandler does not clear or run audible_closure_ during WebContentsDestroyed(). When the Reading Mode side panel is subsequently closed, the page handler’s destructor runs, but since the observed WebContents is already gone, the internal checks prevent a clean reset of the closure, causing the ScopedClosureRunner destructor to delete the audible client registration after the AudioStreamMonitor has already been freed. This results in a Use-After-Free when attempting to access the AudioStreamMonitor instance.

Potential Attack Steps

(Note: These are potential steps based on static analysis, as our tooling does not yet have the ability to run proof-of-concept code.)

  1. A user opens Reading Mode, launching the side-panel handler (ReadAnythingUntrustedPageHandler) in the Browser process, bound to the sandboxed chrome-untrusted://read-anything-side-panel.top-chrome/ renderer.
  2. The attacker compromises this sandboxed renderer (e.g., via a renderer exploit) and sends a Mojo IPC message calling OnReadAloudAudioStateChange(true).
  3. The browser process executes the call, storing a base::ScopedClosureRunner in audible_closure_ which contains a raw_ptr<AudioStreamMonitor> pointing to the active tab’s AudioStreamMonitor.
  4. The user closes the active tab, causing the WebContentsImpl and its inline AudioStreamMonitor to be destroyed. ReadAnythingUntrustedPageHandler::WebContentsDestroyed() is called, but it fails to clear audible_closure_.
  5. The side panel is closed, triggering the destruction of ReadAnythingUntrustedPageHandler.
  6. The destructor calls OnReadAloudAudioStateChange(false), but because the tab is already destroyed, main_observer_->web_contents() returns nullptr. The guard if (contents) evaluates to false, and audible_closure_.RunAndReset() is skipped.
  7. audible_closure_ is destroyed during member teardown, executing the wrapped closure. This deletes the client registration, which attempts to access the already-freed AudioStreamMonitor via the dangling pointer in ~AudibleClientRegistration(), resulting in a Use-After-Free.

Code References

  • chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc:

    • OnReadAloudAudioStateChange (lines 952-966)
    • ~ReadAnythingUntrustedPageHandler (lines 470-480)
    • WebContentsDestroyed (lines 554-556)
  • content/browser/media/audio_stream_monitor.cc:

    • ~AudibleClientRegistration (lines 38-40)

Suggested Remediation

To prevent the base::ScopedClosureRunner from holding a dangling pointer or running after the associated WebContents has been destroyed, explicitly clear or reset audible_closure_ when the observed WebContents is destroyed. This can be done by modifying ReadAnythingUntrustedPageHandler::WebContentsDestroyed() as follows:

void ReadAnythingUntrustedPageHandler::WebContentsDestroyed() {
  translate_observation_.Reset();
  audible_closure_.Reset();
}

Evaluated with Chrome root at commit: 5133b93d189b383c37805b1cf3a9d2dbfe8d7379


Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:

  • If you are familiar with the severity guidelines, you may adjust the severity.
  • If this is a false positive, and there’s no work to be done, please close as WAI.
  • If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.

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.

View on issue tracker