CVE-2026-17866
Overview
Files Changed
chrome/browser/android/tab_android.cc
Patch
From 1ed90ec8ff93b273e9785c69e927f0ea5dfa1d34 Mon Sep 17 00:00:00 2001 From: Calder Kitagawa <[email protected]> Date: Tue, 16 Jun 2026 09:13:17 -0700 Subject: [PATCH] [Tab] Use ToTabAndroidOrNull for FromTabHandle Ensure valid conversion even if the TabHandle/TabInterface is for a TabInterfaceAndroid. Fixed: 520525732 Change-Id: I80f3d00713afd594956f9d50671a1029a689a519 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7951099 Auto-Submit: Calder Kitagawa <[email protected]> Reviewed-by: Fiaz Muhammad <[email protected]> Commit-Queue: Calder Kitagawa <[email protected]> Commit-Queue: Fiaz Muhammad <[email protected]> Cr-Commit-Position: refs/heads/main@{#1647630} --- diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc index 60a4f29..3107b9e 100644 --- a/chrome/browser/android/tab_android.cc +++ b/chrome/browser/android/tab_android.cc @@ -27,6 +27,7 @@ #include "chrome/browser/android/compositor/tab_content_manager.h" #include "chrome/browser/android/media_state_observer.h" #include "chrome/browser/android/selection/chrome_selection_dropdown_menu_delegate.h" +#include "chrome/browser/android/tab_android_conversions.h" #include "chrome/browser/android/tab_features.h" #include "chrome/browser/android/tab_web_contents_delegate_android.h" #include "chrome/browser/android/web_contents_theme_client.h" @@ -127,7 +128,7 @@ // static TabAndroid* TabAndroid::FromTabHandle(tabs::TabHandle handle) { - return static_cast<TabAndroid*>(handle.Get()); + return tabs::ToTabAndroidOrNull(handle.Get()); } // static
Original Bug Report
Potential Browser-Process Type Confusion in TabAndroid::FromTabHandle via Glic Actor
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 class-level type confusion vulnerability exists in the Android implementation of Glic Actor. The method TabAndroid::FromTabHandle performs an unsafe static downcast of a base pointer to TabAndroid* without type validation. This can allow a compromised guest renderer to inject a tab handle corresponding to TabInterfaceAndroid, leading to virtual method table corruption and potential arbitrary code execution in the browser process.
Affected files:
chrome/browser/android/tab_android.ccchrome/browser/android/tab_android.hchrome/browser/actor/android/actor_task_android.cc
Estimated timestamp from git blame: 2026-03-18
Abstract
There is a potential class-level type confusion vulnerability in TabAndroid::FromTabHandle on Android. The method performs an unsafe static downcast of a tabs::TabInterface* to TabAndroid*. However, in the Android tab collection model, tabs are often wrapped inside TabInterfaceAndroid instances (which inherit from tabs::TabInterface but are not subclasses of TabAndroid).
Because both concrete classes are stored in a sequential integer-backed handle database (SessionMappedTabHandleFactory), an attacker who can inject a raw handle integer corresponding to a TabInterfaceAndroid instance into a context expecting TabAndroid can trigger type confusion. If virtual methods are subsequently invoked on the type-confused pointer, it can lead to virtual table corruption and potential Remote Code Execution (RCE) in the browser process.
Vulnerability Analysis & Memory Layout
1. Sibling Class Relationship
TabAndroid and TabInterfaceAndroid are sibling classes that share a common base class, tabs::TabInterface, but do not inherit from each other:
-
TabAndroid(chrome/browser/android/tab_android.hlines 64-66):class TabAndroid : public tabs::TabInterface, public TabAndroidDataProvider, public base::SupportsUserData -
TabInterfaceAndroid(chrome/browser/android/tab_interface_android.hline 20):class TabInterfaceAndroid : public tabs::TabInterface
2. Unsafe Static Downcast
In chrome/browser/android/tab_android.cc (lines 129-131), the method FromTabHandle is implemented as follows:
TabAndroid* TabAndroid::FromTabHandle(tabs::TabHandle handle) {
return static_cast<TabAndroid*>(handle.Get());
}
Here, handle.Get() retrieves a tabs::TabInterface* from SessionMappedTabHandleFactory. Performing a static_cast<TabAndroid*> on a pointer that actually points to a TabInterfaceAndroid instance is invalid downcasting and results in type confusion.
3. Memory Effect and Offset Misalignment
TabAndroid utilizes multiple inheritance. When virtual methods declared on its second base class, TabAndroidDataProvider (such as GetAndroidId()), are called, the compiler applies a static “this-adjustment” offset to the pointer.
When this offset is applied to a type-confused TabInterfaceAndroid pointer, the offset lands inside other internal members of TabInterfaceAndroid (for example, ui::UnownedUserDataHost unowned_user_data_host_ at tab_interface_android.h line 84). De-referencing the resulting pointer to locate the virtual method table (vtable) fetches arbitrary heap data, resulting in a wild indirect call and control-flow hijacking inside the high-privilege Browser process.
Potential Injection Path
The Glic guest webview runs remote untrusted content in a separate sandboxed renderer process. A compromised guest renderer can interact with the trusted WebUI layer (chrome://glic) via the glicBrowser JS API:
-
WebUI Client Forwarding: The WebUI JavaScript helper at
chrome/browser/resources/glic/glic_api_impl/host/host_from_client.tsforwards guest-suppliedtabIdintegers verbatim to the browser process via Mojo IPC interfaces. -
Mojo Ingress:
GlicActorClientSession::PauseActorTask(chrome/browser/glic/actor/glic_actor_task_manager.cclines 667-670) consumes the raw integer from Mojo and constructs atabs::TabInterface::Handle:tabs::TabInterface::Handle handle; if (tab_handle.has_value()) { handle = tabs::TabInterface::Handle(*tab_handle); } -
Task Registration: The task manager registers the handle into the active task’s controlled tab list via
task->AddTab(handle, ...)(chrome/browser/glic/actor/glic_actor_task_manager.ccline 690). The lookup is successful sinceTabInterfaceAndroidis registered under this handle in the factory. -
JNI Query Sink: When an Android system event (such as entering Picture-in-Picture or bringing a tab to front) occurs, the Java layer queries the native task for its tab list via
ActorTaskAndroid::GetLastActedTabs(chrome/browser/actor/android/actor_task_android.cclines 96-105):for (const auto& handle : tab_handles) { if (auto* tab_android = TabAndroid::FromTabHandle(handle)) { tab_ids.push_back(tab_android->GetAndroidId()); } }The loop invokes
TabAndroid::FromTabHandle(handle)which executes the type-confused cast, then callstab_android->GetAndroidId(), triggering the wild indirect call.
Potential Steps to Trigger (Suggested/Theoretical)
Note: These are potential steps, as our tooling does not have the ability to run code or verify execution behavior on a live device.
- Launch Chromium on Android with
--enable-features=GlicActor(or when the Glic Actor feature is active). - Compromise the sandboxed Glic guest renderer running remote content.
- From the guest context, post a message to the WebUI to invoke
pauseActorTaskwith an arbitrary integer handle corresponding to a liveTabInterfaceAndroidwrapper (handles are sequentialint32_tvalues). - The WebUI forwards the handle to the browser process, registering the
TabInterfaceAndroidhandle intocontrolled_tabs_. - Trigger an Android system event (e.g., toggling Picture-in-Picture) to force a JNI transition to
ActorTaskAndroid::GetLastActedTabs, executing the virtual method calltab_android->GetAndroidId()on the confused pointer.
Mitigating Factors
- Feature Gating: The Glic Actor functionality (
features::kGlicActor) is currentlyFEATURE_DISABLED_BY_DEFAULTon Android (chrome/common/chrome_features.ccline 192).
Suggested Fix
To remediate this issue, direct static downcasts of tabs::TabInterface* to TabAndroid* should be prohibited. Instead, the safe conversion helpers defined in chrome/browser/android/tab_android_conversions.h must be used.
Modify TabAndroid::FromTabHandle inside chrome/browser/android/tab_android.cc to utilize tabs::ToTabAndroidOrNull:
// static
TabAndroid* TabAndroid::FromTabHandle(tabs::TabHandle handle) {
return tabs::ToTabAndroidOrNull(handle.Get());
}
Evaluated with Chrome root at commit: e9507a33bb4148ee071aaaf8a7e9ad68770359bf
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.