Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in DigitalCredentials
DescriptionUse after free in DigitalCredentials
ComponentDigitalCredentials
Bug ClassUAF
Tracker514741076
Fix commit2da7f965b3d8 (chromium/src) +6/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-16

Changed Functions

FunctionChangeNotes
if
content/browser/digital_credentials/digital_identity_request_impl.cc
modified

Files Changed

  • content/browser/digital_credentials/digital_identity_request_impl.cc
From 2da7f965b3d829ef5e0db086f285b932a8930b81 Mon Sep 17 00:00:00 2001
From: Mohamed Amir Yosef <[email protected]>
Date: Tue, 09 Jun 2026 04:13:11 -0700
Subject: [PATCH] [DC] Add weak_this guard in Abort()

In `DigitalIdentityRequestImpl::Abort()`, executing the
`update_interstitial_on_abort_callback_` can result in the closure of a
tab-modal Widget (the safety interstitial) on desktop platforms. This UI
closure can synchronously destroy the hosting `WebContents` via
activation observers, which consequently destroys the
`DigitalIdentityRequestImpl` instance. Calling
`CompleteRequestWithError` on the `this` pointer after the callback
leads to a use-after-free (UAF).

This CL adds a `base::WeakPtr` liveness check immediately after running
the callback, similar to the existing guard in
`CompleteRequestWithStatus()`.

This is a defense-in-depth fix.

Fixed: 514741076
Change-Id: I878886c677797ebe280f32c4be806d6472b453c4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7913162
Reviewed-by: Christoph Schwering <[email protected]>
Commit-Queue: Mohamed Amir Yosef <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1643850}
---

diff --git a/content/browser/digital_credentials/digital_identity_request_impl.cc b/content/browser/digital_credentials/digital_identity_request_impl.cc
index f10b430..2291d64 100644
--- a/content/browser/digital_credentials/digital_identity_request_impl.cc
+++ b/content/browser/digital_credentials/digital_identity_request_impl.cc
@@ -758,10 +758,16 @@
     return;
   }
 
+  base::WeakPtr<DigitalIdentityRequestImpl> weak_this =
+      weak_ptr_factory_.GetWeakPtr();
   if (update_interstitial_on_abort_callback_) {
     std::move(update_interstitial_on_abort_callback_).Run();
   }
 
+  if (!weak_this) {
+    return;
+  }
+
   CompleteRequestWithError(RequestStatusForMetrics::kErrorAborted);
 }
 
Loading diff…

Original Bug Report

reported by [email protected]

Potential Browser-Process UAF in DigitalIdentityRequestImpl::Abort()

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 use-after-free vulnerability exists in DigitalIdentityRequestImpl::Abort() due to missing liveness checks after a UI-closing callback. On desktop platforms, executing this callback can synchronously destroy the hosting WebContents and the DigitalIdentityRequestImpl object itself. Subsequent access to the object’s members results in a use-after-free in the browser process.

Affected files:

  • content/browser/digital_credentials/digital_identity_request_impl.cc
  • content/browser/digital_credentials/digital_identity_request_impl.h

Estimated timestamp from git blame: 2024-05-24

Vulnerability Details

A potential use-after-free (UAF) vulnerability has been identified in the browser process within DigitalIdentityRequestImpl::Abort(). The DigitalIdentityRequestImpl class is a DocumentService, meaning its lifetime is tied to the RenderFrameHost and its associated WebContents.

Root Cause

In content/browser/digital_credentials/digital_identity_request_impl.cc, the Abort() method executes a callback that can trigger the synchronous destruction of the DigitalIdentityRequestImpl instance:

void DigitalIdentityRequestImpl::Abort() {
  if (!callback_) {
    return;
  }

  if (update_interstitial_on_abort_callback_) {
    std::move(update_interstitial_on_abort_callback_).Run(); // [1]
  }

  CompleteRequestWithError(RequestStatusForMetrics::kErrorAborted); // [2]
}

At [1], update_interstitial_on_abort_callback_ is executed. On desktop platforms, this callback typically closes a tab-modal Widget (the safety interstitial). As documented by developers in a similar context in CompleteRequestWithStatus() (lines 458-461), closing this class of UI can synchronously destroy the hosting WebContents (via activation observers) and consequently the DigitalIdentityRequestImpl object.

At [2], the code proceeds to call CompleteRequestWithError() on the this pointer. If the object was destroyed during the callback at [1], this results in a use-after-free. While CompleteRequestWithStatus() (called by CompleteRequestWithError) contains its own base::WeakPtr guard for subsequent operations, it cannot prevent a UAF if the object is already freed before the function is entered.

Potential Impact

This issue results in a browser-process UAF. Since DigitalIdentityRequestImpl is a DocumentService, its Mojo implementation is not protected by MiraclePtr during the lifecycle of an IPC dispatch (as Mojo internal pointers frequently use RAW_PTR_EXCLUSION). An attacker who successfully reclaims the freed memory could potentially hijack control flow via the provider_ unique pointer or the response callback, leading to remote code execution (RCE) in the browser process and a sandbox escape.

Suggested Reproductions Steps (Potential)

  1. From a compromised renderer, bind the blink.mojom.DigitalIdentityRequest interface.
  2. Initiate a digital identity request (e.g., via Get()) that triggers a safety interstitial (common for high-risk origins on Desktop).
  3. Send an Abort() message via the Mojo remote.
  4. If the WebContents is hosted in a container that closes on focus loss (such as an extension popup), the UI closure triggered by Abort() may synchronously destroy the WebContents and the DigitalIdentityRequestImpl object.
  5. The browser process resumes execution in Abort() and attempts to access the freed this pointer, triggering the UAF.

Suggested Fix

Apply a base::WeakPtr guard in Abort() similar to the one used in CompleteRequestWithStatus(). Verify the liveness of the object immediately after running update_interstitial_on_abort_callback_:

void DigitalIdentityRequestImpl::Abort() {
  if (!callback_) {
    return;
  }

  base::WeakPtr<DigitalIdentityRequestImpl> weak_this = weak_ptr_factory_.GetWeakPtr();
  if (update_interstitial_on_abort_callback_) {
    std::move(update_interstitial_on_abort_callback_).Run();
  }

  if (!weak_this) {
    return;
  }

  CompleteRequestWithError(RequestStatusForMetrics::kErrorAborted);
}

Evaluated with Chrome root at commit: 29093e11cf509e3593f6229e4b1b075cca356049


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