Critical chrome UAF 🔧 Commit mapped

Overview

Critical
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Shared Tab Groups
DescriptionUse after free in Shared Tab Groups
ComponentShared Tab Groups
Bug ClassUAF
Tracker522307103
Fix commit9731d1143de6 (chromium/src) +39/-3
CISA KEVNot listed
CreditedGoogle
Disclosed2026-09-01

Changed Functions

FunctionChangeNotes
if
chrome/browser/collaboration/android/collaboration_controller_delegate_android.cc
modified
if
chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImpl.java
modified

Files Changed

  • chrome/browser/collaboration/android/collaboration_controller_delegate_android.cc
  • chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImpl.java
  • chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImplUnitTest.java
From 9731d1143de694cccb2a8d15616661ea741156d5 Mon Sep 17 00:00:00 2001
From: Hailey Wang <haileywang@google.com>
Date: Wed, 24 Jun 2026 13:07:11 -0700
Subject: [PATCH] [Collaboration] Fix java callback cleanup after flow finished

Bug: 522307103
Change-Id: Ifc7936c51b9c2e9d94934be43675fa41cdbeb294
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7926580
Commit-Queue: Hailey Wang <haileywang@google.com>
Reviewed-by: Siddhartha S <ssid@chromium.org>
Reviewed-by: Ritika Gupta <ritikagup@google.com>
Cr-Commit-Position: refs/heads/main@{#1651927}
---

diff --git a/chrome/browser/collaboration/android/collaboration_controller_delegate_android.cc b/chrome/browser/collaboration/android/collaboration_controller_delegate_android.cc
index f6391cb..1cbe88a4 100644
--- a/chrome/browser/collaboration/android/collaboration_controller_delegate_android.cc
+++ b/chrome/browser/collaboration/android/collaboration_controller_delegate_android.cc
@@ -33,6 +33,9 @@
     int64_t callback) {
   std::unique_ptr<ResultCallback> callback_ptr =
       conversion::GetNativeResultCallbackFromJava(callback);
+  if (!callback_ptr) {
+    return;
+  }
   CollaborationControllerDelegate::Outcome outcome =
       static_cast<CollaborationControllerDelegate::Outcome>(joutcome);
   std::move(*callback_ptr).Run(outcome);
@@ -43,6 +46,9 @@
     int64_t callback) {
   std::unique_ptr<base::OnceClosure> callback_ptr =
       conversion::GetNativeExitCallbackFromJava(callback);
+  if (!callback_ptr) {
+    return;
+  }
   std::move(*callback_ptr).Run();
 }
 
@@ -51,6 +57,9 @@
     int64_t callback) {
   std::unique_ptr<base::OnceClosure> callback_ptr =
       conversion::GetNativeExitCallbackFromJava(callback);
+  if (!callback_ptr) {
+    return;
+  }
   callback_ptr.reset();
 }
 
@@ -63,6 +72,9 @@
     int64_t callback) {
   std::unique_ptr<ResultWithGroupTokenCallback> callback_ptr =
       conversion::GetNativeResultWithGroupTokenCallbackFromJava(callback);
+  if (!callback_ptr) {
+    return;
+  }
   CollaborationControllerDelegate::Outcome outcome =
       static_cast<CollaborationControllerDelegate::Outcome>(joutcome);
 
diff --git a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImpl.java b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImpl.java
index dd9e65b..756f55f 100644
--- a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImpl.java
+++ b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImpl.java
@@ -855,8 +855,10 @@
         if (mFeatureEngagementLock != null) {
             mFeatureEngagementLock.release();
         }
-        if (mExitCallback != 0) {
-            CollaborationControllerDelegateImplJni.get().deleteExitCallback(mExitCallback);
+        long tempCallback = mExitCallback;
+        mExitCallback = 0;
+        if (tempCallback != 0) {
+            CollaborationControllerDelegateImplJni.get().deleteExitCallback(tempCallback);
         }
     }
 
@@ -874,7 +876,9 @@
         mThreadChecker.assertOnValidThread();
         long tempCallback = mExitCallback;
         mExitCallback = 0;
-        CollaborationControllerDelegateImplJni.get().runExitCallback(tempCallback);
+        if (tempCallback != 0) {
+            CollaborationControllerDelegateImplJni.get().runExitCallback(tempCallback);
+        }
     }
 
     @SuppressWarnings("NullAway")
diff --git a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImplUnitTest.java b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImplUnitTest.java
index 89a0b99..55ea56e 100644
--- a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImplUnitTest.java
+++ b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImplUnitTest.java
@@ -327,6 +327,26 @@
     }
 
     @Test
+    public void testDestroyAfterFlowFinishedDoesNotRunExitCallback() {
+        createDelegate(FlowType.JOIN);
+        long prepareResultCallback = 1;
+        long exitCallback = 2;
+
+        mCollaborationControllerDelegateImpl.prepareFlowUI(exitCallback, prepareResultCallback);
+
+        // Simulate flow finished, which deletes exitCallback.
+        mCollaborationControllerDelegateImpl.onFlowFinished();
+
+        // Simulate subsequent destroy.
+        mCollaborationControllerDelegateImpl.destroy();
+
+        // Delete should have been called, but runExitCallback should never be called.
+        verify(mCollaborationControllerDelegateImplNativeMock).deleteExitCallback(eq(exitCallback));
+        verify(mCollaborationControllerDelegateImplNativeMock, never())
+                .runExitCallback(eq(exitCallback));
+    }
+
+    @Test
     public void testPromoteTabGroup() {
         createDelegate(FlowType.JOIN);
         long resultCallback = 1;
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.