CVE-2026-12441
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
forui/gtk/select_file_dialog_linux_gtk.cc |
modified |
Files Changed
ui/gtk/select_file_dialog_linux_gtk.cc
Patch
From 0852956e05514f481fb7318d884e3b3a6b48ef79 Mon Sep 17 00:00:00 2001
From: Tom Anderson <thomasanderson@chromium.org>
Date: Mon, 08 Jun 2026 15:41:26 -0700
Subject: [PATCH] [Gtk] Fix Use-After-Free in SelectFileDialogLinuxGtk destructor
In SelectFileDialogLinuxGtk::~SelectFileDialogLinuxGtk(), calling
GtkWindowDestroy(dialog) synchronously disposes and finalizes the dialog
widget before OnFileChooserDestroy() runs. Because
OnFileChooserDestroy() accesses the dialog (specifically inside
ClearAuraTransientParent to clear transient parent properties), this
results in a use-after-free on the GLib heap.
This CL resolves this by running OnFileChooserDestroy() to clear
transient parent metadata before synchronously destroying the GtkWidget
with GtkWindowDestroy().
Fixed: 520157118
Change-Id: I15f8596e17fe54abdae95410066d125d702eb0a3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7909293
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Auto-Submit: Thomas Anderson <thomasanderson@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1643498}
---
diff --git a/ui/gtk/select_file_dialog_linux_gtk.cc b/ui/gtk/select_file_dialog_linux_gtk.cc
index adf2a549..9e3390f 100644
--- a/ui/gtk/select_file_dialog_linux_gtk.cc
+++ b/ui/gtk/select_file_dialog_linux_gtk.cc
@@ -207,8 +207,11 @@
}
for (GtkWidget* dialog : dialogs) {
CHECK(dialog);
- GtkWindowDestroy(dialog);
+ // `GtkWindowDestroy()` synchronously drops the only reference and frees
+ // the dialog, so run `OnFileChooserDestroy()` (which calls
+ // `g_object_set_data()` on `dialog`) first to avoid a use-after-free.
OnFileChooserDestroy(dialog);
+ GtkWindowDestroy(dialog);
}
CHECK(dialogs_.empty());
}
Original Bug Report
Browser-Process Use-After-Free in SelectFileDialogLinuxGtk Destructor
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 heap use-after-free (UAF) vulnerability exists in the browser process of Chromium on Linux when using the GTK file chooser dialog. In the destructor of SelectFileDialogLinuxGtk, destroying the GTK widget synchronously frees the object, while a subsequent callback accesses the freed dialog pointer to clear the transient parent data. This results in a use-after-free on the GLib/system heap, bypassing PartitionAlloc and MiraclePtr protections.
Affected files:
ui/gtk/select_file_dialog_linux_gtk.cc
Estimated timestamp from git blame: 2021-03-26
Description
A potential heap Use-After-Free (UAF) vulnerability exists in the GTK file chooser implementation for Linux (ui/gtk/select_file_dialog_linux_gtk.cc). The bug is located in the destructor SelectFileDialogLinuxGtk::~SelectFileDialogLinuxGtk(), where a native GTK widget is synchronously destroyed, followed by an immediate access to the same widget pointer.
In SelectFileDialogLinuxGtk::~SelectFileDialogLinuxGtk():
for (GtkWidget* dialog : dialogs) {
CHECK(dialog);
GtkWindowDestroy(dialog);
OnFileChooserDestroy(dialog);
}
GtkWindowDestroy(dialog)dispatches to eithergtk_window_destroy(GTK4) orgtk_widget_destroy(GTK3). Since Chromium does not hold any additional reference count (org_object_ref) on the dialog, this synchronously triggers the GObject dispose and finalize phases, freeing the memory of theGtkWidgeton the GLib/system heap.- Immediately after,
OnFileChooserDestroy(dialog)is called with the freeddialogpointer. - Inside
OnFileChooserDestroy, ifstate.parent(the native browser window) is non-null, it callsClearAuraTransientParent:
void SelectFileDialogLinuxGtk::OnFileChooserDestroy(GtkWidget* dialog) {
...
if (state.parent) {
CHECK(dialog);
ClearAuraTransientParent(dialog, state.parent, platform_);
state.parent->RemoveObserver(this);
}
...
}
ClearAuraTransientParentexecutesg_object_set_data(G_OBJECT(dialog), kAuraTransientParent, nullptr), which performs aG_IS_OBJECTcheck and dereferences the freeddialogpointer to clear the associated transient parent property on the GObject. This constitutes a Use-After-Free read and write outside of PartitionAlloc (thus unaffected by MiraclePtr/BackupRefPtr).
Potential Attack Scenario / Trigger Steps
Note: These are potential steps based on code analysis; our tooling does not currently have the capability to run a live exploit verification.
- Environment: Linux desktop using GTK where the
org.freedesktop.portal.FileChooserDBus interface is version < 3 or unavailable, forcingSelectFileDialogLinuxPortalto fall back toSelectFileDialogLinuxGtk. - Action: A web page requests a file dialog via
showOpenFilePicker()under a user activation gesture, then immediately triggers a frame navigation (e.g.,location = 'about:blank') shortly after. - Navigation Cancellation: The navigation invalidates the document, causing
WebContentsBasedCancellerto invoke the cancel callback, which callsFileSystemChooser::FileSelectionCanceled()->delete this;. - Destruction Sequence:
~FileSystemChooserinvokesdialog_->ListenerDestroyed(), which resetsfallback_dialog_insideSelectFileDialogLinuxPortal, dropping the last remaining reference toSelectFileDialogLinuxGtk. - UAF Trigger:
~SelectFileDialogLinuxGtk()executes, destroying the dialog withGtkWindowDestroyand subsequently dereferencing it insideOnFileChooserDestroy.
Suggested Fix
To resolve this issue, the lifetime management during destruction should be inverted. OnFileChooserDestroy(dialog) must be called before the widget is destroyed via GtkWindowDestroy(dialog). This ensures that all operations accessing the widget’s properties (such as clearing transient parent associations) are performed while the object’s memory is fully valid.
--- a/ui/gtk/select_file_dialog_linux_gtk.cc
+++ b/ui/gtk/select_file_dialog_linux_gtk.cc
@@ -207,8 +207,8 @@ SelectFileDialogLinuxGtk::~SelectFileDialogLinuxGtk() {
}
for (GtkWidget* dialog : dialogs) {
CHECK(dialog);
- GtkWindowDestroy(dialog);
OnFileChooserDestroy(dialog);
+ GtkWindowDestroy(dialog);
}
CHECK(dialogs_.empty());
}
Evaluated with Chrome root at commit: d8b226a3be7c9c1ac9240c09e14698866c82e4ac
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.