CVE-2026-13800
Overview
Files Changed
chrome/updater/ipc/ipc_security_linux.ccchrome/updater/ipc/ipc_security_mac.ccchrome/updater/ipc/ipc_security_win.cc
Patch
From c55a1e0eb4c39d9691f8668d6e933ff50b857bfc Mon Sep 17 00:00:00 2001 From: Noah Rose Ledesma <[email protected]> Date: Tue, 19 May 2026 11:29:03 -0700 Subject: [PATCH] Consider updater clients as untrusted Use the MOJO_SEND_INVITATION_FLAG_UNTRUSTED_PROCESS flag when sending Mojo invitations to clients connecting to the updater's server. This prevents the passing of certain handle types which are unused in updater communications. This helps reduce the attack surface of potential LPEs via the updater's Mojo interface. Bug: 500108770 Change-Id: Idb3bf3da623e61e6dd7e7e5fe71812b06a6a6964 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7850556 Reviewed-by: Sorin Jianu <[email protected]> Auto-Submit: Noah Rose Ledesma <[email protected]> Commit-Queue: Sorin Jianu <[email protected]> Cr-Commit-Position: refs/heads/main@{#1633025} --- diff --git a/chrome/updater/ipc/ipc_security_linux.cc b/chrome/updater/ipc/ipc_security_linux.cc index 13b716c..0e88fa8 100644 --- a/chrome/updater/ipc/ipc_security_linux.cc +++ b/chrome/updater/ipc/ipc_security_linux.cc @@ -9,6 +9,7 @@ #include "components/named_mojo_ipc_server/connection_info.h" #include "components/named_mojo_ipc_server/endpoint_options.h" +#include "mojo/public/c/system/invitation.h" #include "mojo/public/cpp/platform/named_platform_channel.h" namespace updater { @@ -25,6 +26,8 @@ options.message_pipe_id = named_mojo_ipc_server::EndpointOptions::kUseIsolatedConnection; options.require_same_peer_user = false; + options.extra_send_invitation_flags = + MOJO_SEND_INVITATION_FLAG_UNTRUSTED_PROCESS; return options; } diff --git a/chrome/updater/ipc/ipc_security_mac.cc b/chrome/updater/ipc/ipc_security_mac.cc index 913179e..ee9c991 100644 --- a/chrome/updater/ipc/ipc_security_mac.cc +++ b/chrome/updater/ipc/ipc_security_mac.cc @@ -10,6 +10,7 @@ #include "components/named_mojo_ipc_server/connection_info.h" #include "components/named_mojo_ipc_server/endpoint_options.h" +#include "mojo/public/c/system/invitation.h" #include "mojo/public/cpp/platform/named_platform_channel.h" namespace updater { @@ -22,7 +23,8 @@ named_mojo_ipc_server::EndpointOptions CreateServerEndpointOptions( const mojo::NamedPlatformChannel::ServerName& server_name) { return {server_name, - named_mojo_ipc_server::EndpointOptions::kUseIsolatedConnection}; + named_mojo_ipc_server::EndpointOptions::kUseIsolatedConnection, + MOJO_SEND_INVITATION_FLAG_UNTRUSTED_PROCESS}; } } // namespace updater diff --git a/chrome/updater/ipc/ipc_security_win.cc b/chrome/updater/ipc/ipc_security_win.cc index ece8a7c..13a5686 100644 --- a/chrome/updater/ipc/ipc_security_win.cc +++ b/chrome/updater/ipc/ipc_security_win.cc @@ -7,6 +7,7 @@ #include "chrome/updater/get_updater_scope.h" #include "components/named_mojo_ipc_server/connection_info.h" #include "components/named_mojo_ipc_server/endpoint_options.h" +#include "mojo/public/c/system/invitation.h" #include "mojo/public/cpp/platform/named_platform_channel.h" namespace updater { @@ -25,7 +26,8 @@ const mojo::NamedPlatformChannel::ServerName& server_name) { named_mojo_ipc_server::EndpointOptions options{ server_name, - named_mojo_ipc_server::EndpointOptions::kUseIsolatedConnection}; + named_mojo_ipc_server::EndpointOptions::kUseIsolatedConnection, + MOJO_SEND_INVITATION_FLAG_UNTRUSTED_PROCESS}; if (IsSystemInstall()) { // A DACL to grant:
Original Bug Report
Potential Local Privilege Escalation in Chrome Updater via Mojo Ipcz handle relaying
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 without the security team.
Overview: A potential vulnerability in the Windows Chrome Updater could allow an unprivileged local user to escalate privileges to SYSTEM. The flaw arises because the updater establishes isolated IPC connections as fully trusted brokers, allowing an attacker to exploit the Mojo/Ipcz relay mechanism. By establishing two connections, an attacker could force the SYSTEM process to adopt its own internal handles and duplicate them into the attacker’s process.
Affected files:
mojo/core/ipcz_driver/transport.ccmojo/core/ipcz_driver/invitation.ccthird_party/ipcz/src/ipcz/node_link.ccthird_party/ipcz/src/ipcz/node.ccmojo/core/ipcz_driver/wrapped_platform_handle.cccomponents/named_mojo_ipc_server/named_mojo_message_pipe_server.ccchrome/updater/ipc/ipc_security_win.cc
Estimated timestamp from git blame: 2025-05-08
Summary
There is a potential Local Privilege Escalation (LPE) to SYSTEM in the Chrome Updater on Windows. The vulnerability stems from how NamedMojoMessagePipeServer configures mojo::IsolatedConnections, inadvertently granting connected clients kTrusted and kBroker status within the Mojo Ipcz driver. A local attacker can abuse this trust by establishing two connections and sending a crafted RelayMessage to force the Updater to duplicate its own internal handles (such as process tokens) into the attacker’s process.
Technical Details
The Chrome Updater service runs as SYSTEM and hosts a NamedMojoIpcServer. The DACL for its named pipe (\\.\pipe\mojo.{UpdaterServerName}) correctly allows Authenticated Users to connect. However, the subsequent handling of the connection introduces a critical flaw:
- Improper Trust Assignment: When a client connects,
NamedMojoMessagePipeServer::OnClientConnectedopens the client process withPROCESS_DUP_HANDLEand creates anIsolatedConnection. TheIsolatedConnectionsetsMOJO_SEND_INVITATION_FLAG_ISOLATEDbut omitsMOJO_SEND_INVITATION_FLAG_UNTRUSTED_PROCESS. Consequently,mojo/core/ipcz_driver/invitation.cctreats the remote endpoint asTransport::ProcessTrust::kTrustedandTransport::kBroker. - Handle Adoption Bypass (
DecodeHandle): Because the attacker’s connection is considered akBroker, the attacker can send a serialized handle withHandleOwner::kRecipient. Inmojo/core/ipcz_driver/transport.cc,DecodeHandleskips duplication forkRecipienthandles arriving from brokers. The SYSTEM process blindly callsGetHandleInformationon the attacker-supplied raw integer and adopts it as a validPlatformHandlebelonging to the SYSTEM process itself. - Relay Mechanism: The attacker can send this handle inside a
msg::RelayMessagedestined for a second connection they control. The IpczNoderouting logic blindly forwards the deserialized driver objects (now containing the valid SYSTEM handle) to the destination link. - Unsafe Duplication (
EncodeHandle): When serializing the message for the attacker’s second connection,EncodeHandlesees that the destination iskTrusted(due to the missing untrusted flag). It therefore skips theMaybeCheckIfHandleIsUnsafesecurity check, which would normally block sensitive handles like Tokens or Processes. It proceeds to callDuplicateHandlewithDUPLICATE_SAME_ACCESS, copying the SYSTEM handle directly into the attacker’s process using thePROCESS_DUP_HANDLEacquired during connection setup.
Potential Steps to Reproduce
Note: These are potential steps to trigger the vulnerability based on code analysis. Our tooling does not yet have the ability to run a working Proof of Concept.
- Run as a non-privileged local user and open two client connections (C1 and C2) to the SYSTEM updater named pipe.
- Establish the Mojo/Ipcz
NodeLinkby exchangingConnectFromBrokerToBrokermessages, registering two different Node names (e.g., N1 for C1 and N2 for C2). - Over C1, send a
msg::RelayMessagetargeted at N2. Include akWrappedPlatformHandledriver object withhandle_owner = kRecipientand a raw handle value to test (e.g.,0x4). - The SYSTEM updater receives the message on C1. Due to the
kBrokertrust bypass inDecodeHandle, it adopts its own internal handle0x4and prepares to relay it to C2. - During transmission to C2,
EncodeHandleskipsMaybeCheckIfHandleIsUnsafe()because the remote process iskTrusted. It callsDuplicateHandleto copy the handle into the attacker’s C2 process. - Retrieve the duplicated handle from C2. Use
NtQueryObjectto inspect the handle type. Repeat the process, incrementing the handle value (e.g.,0x8,0xC), until a SYSTEM token or process handle is extracted.
Suggested Fix
- Update
NamedMojoMessagePipeServer::OnClientConnected(or the underlyingIsolatedConnectionutilities) to explicitly passMOJO_SEND_INVITATION_FLAG_UNTRUSTED_PROCESSwhen accepting connections from potentially untrusted clients, even for isolated connections. This will ensureremote_process_trustis set tokUntrusted, enabling theMaybeCheckIfHandleIsUnsafemitigations. - Review the trust model for
IsolatedConnections in Mojo/Ipcz. Treating isolated peers implicitly askBrokerenables powerful handle ownership manipulations (kRecipient) inDecodeHandle. Consider restricting this capability or requiring explicit authorization.
Evaluated with Chrome root at commit: f200f57a19490707ff8bc7aa5de3cbc443a3afad
Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; 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.