CVE-2026-11238
Overview
Files Changed
content/browser/devtools/protocol/tracing_handler.cc
Patch
From d0275cb2dc57814f9096f13a9024a5dd2a827986 Mon Sep 17 00:00:00 2001 From: Danil Somsikov <[email protected]> Date: Thu, 23 Apr 2026 02:12:52 -0700 Subject: [PATCH] Remove unused processPseudoId field from DevTools tracing events. The processPseudoId field was used as a temporary identifier to correlate frames and processes in the browser before a real PID was available. Investigation shows that this field is no longer used by the modern DevTools frontend (it is not referenced in any .ts files). Removing this field simplifies the tracing protocol and eliminates a security concern where the field was leaking raw memory addresses of RenderProcessHost objects. Bug: 496705691 Change-Id: I6703fe1578916afba06ca16e56eda886d4e55145 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7776999 Reviewed-by: Andrey Kosyakov <[email protected]> Auto-Submit: Danil Somsikov <[email protected]> Commit-Queue: Danil Somsikov <[email protected]> Cr-Commit-Position: refs/heads/main@{#1619393} --- diff --git a/content/browser/devtools/protocol/tracing_handler.cc b/content/browser/devtools/protocol/tracing_handler.cc index d3f9aa3..8a54649 100644 --- a/content/browser/devtools/protocol/tracing_handler.cc +++ b/content/browser/devtools/protocol/tracing_handler.cc @@ -177,15 +177,11 @@ base::WeakPtr<TracingHandler> tracing_handler_; }; -std::string GetProcessHostHex(RenderProcessHost* host) { - return base::StringPrintf("0x%" PRIxPTR, reinterpret_cast<uintptr_t>(host)); -} void SendProcessReadyInBrowserEvent(const base::UnguessableToken& frame_token, RenderProcessHost* host) { auto data = std::make_unique<base::trace_event::TracedValue>(); data->SetString("frame", frame_token.ToString()); - data->SetString("processPseudoId", GetProcessHostHex(host)); data->SetInteger("processId", static_cast<int>(host->GetProcess().Pid())); TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ProcessReadyInBrowser", TRACE_EVENT_SCOPE_THREAD, @@ -216,7 +212,6 @@ RenderProcessHost* process_host = frame_host->GetProcess(); const base::Process& process_handle = process_host->GetProcess(); if (!process_handle.IsValid()) { - data->SetString("processPseudoId", GetProcessHostHex(process_host)); frame_host->GetProcess()->PostTaskWhenProcessIsReady( base::BindOnce(&SendProcessReadyInBrowserEvent, frame_host->devtools_frame_token(), process_host));
Original Bug Report
ASLR bypass: Browser-process heap address leak via CDP processPseudoId
Project Fortify, an experimental security project, has identified the following potential security issue.
Overview: The Chrome DevTools Protocol (CDP) Tracing domain leaks raw browser-process RenderProcessHost heap addresses to untrusted clients. This occurs because the processPseudoId field in trace events is populated using the raw pointer value of the host. An untrusted extension with the debugger permission can capture these events during cross-origin navigations, resulting in a deterministic browser-process ASLR bypass.
Affected files:
content/browser/devtools/protocol/tracing_handler.cccontent/browser/devtools/render_frame_devtools_agent_host.cccontent/browser/devtools/web_contents_devtools_agent_host.cc
Estimated timestamp from git blame: 2024-02-06
Description
The Chrome DevTools Protocol (CDP) TracingHandler leaks raw heap addresses from the highly privileged browser process.
In content/browser/devtools/protocol/tracing_handler.cc, the helper function GetProcessHostHex formats a raw RenderProcessHost* as a hexadecimal string:
std::string GetProcessHostHex(RenderProcessHost* host) {
return base::StringPrintf("0x%" PRIxPTR, reinterpret_cast<uintptr_t>(host));
}
During a cross-origin navigation that requires a process switch, a new RenderProcessHost is provisioned. While its underlying OS process is launching asynchronously, process_handle.IsValid() temporarily returns false. If trace events (such as FrameCommittedInBrowser or ProcessReadyInBrowser) are generated during this window, FillFrameData uses GetProcessHostHex to populate the processPseudoId field with the raw browser-process heap address.
Crucially, untrusted DevTools clients (like Chrome Extensions with the debugger permission) are explicitly granted access to the TracingHandler. In content/browser/devtools/devtools_session.h, protocol::TracingHandler is whitelisted in IsDomainAvailableToUntrustedClient<T>(). This allows an extension to deterministically bypass Address Space Layout Randomization (ASLR) in the browser process, providing a powerful primitive for a sandbox escape chain.
Potential Steps to Trigger
(Note: These are suggested steps based on code analysis, as the Flapjack LLM agent does not yet have the ability to run code or execute a live proof of concept.)
- Install Malicious Extension: An attacker installs a Chrome extension possessing the
debuggerpermission. - Attach to Tab: The extension calls
chrome.debugger.attach({tabId: target_tab}, "1.3")to attach to an active page. - Start Tracing: The extension sends the
Tracing.startCDP command with thedisabled-by-default-devtools.timelinecategory. - Trigger Process Switch: The extension initiates a cross-origin navigation in the attached tab (e.g., via
chrome.tabs.update), forcing the creation of a newRenderProcessHost. - Capture the Leak: As the navigation commits before the OS process is fully ready, the browser emits a
FrameCommittedInBrowsertrace event containing the rawRenderProcessHost*address in theprocessPseudoIdfield. - Extract Pointer: The extension parses the DevTools event stream, reads the
processPseudoIdvalue, and uses the leaked heap pointer to bypass browser-process ASLR.
Suggested Fix
Do not use raw memory addresses as identifiers. Instead, use a safe, unique identifier.
A robust fix would be to modify GetProcessHostHex (or remove it entirely) and use the RenderProcessHost’s internal ID (host->GetID()) or generate a base::UnguessableToken specifically for pending processes, mapping it to the eventual OS PID when the process becomes ready.
Evaluated with Chrome root at commit: False
Results from Fortify so far have been promising, but it can be wrong in its deductions. At this time, it does not produce proof of concepts or fuzzer tests. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve Fortify’s accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.