Chrome · Bluetooth
CVE-2026-79001
Logic Error in Bluetooth
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
weak_ptr_factory_device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm |
modified | |
discovery_pending_count_device/bluetooth/bluetooth_remote_gatt_service_mac.mm |
modified |
Files Changed
device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mmdevice/bluetooth/bluetooth_remote_gatt_descriptor_mac.mmdevice/bluetooth/bluetooth_remote_gatt_service_mac.mm
Patch
From ee79c0611ff70932f2672da3d580b2fe69b7b8d0 Mon Sep 17 00:00:00 2001
From: Rob Pitkin <robpitkin@google.com>
Date: Mon, 13 Jul 2026 09:57:17 -0700
Subject: [PATCH] Prevent macOS WebBluetooth GATT identifiers from leaking heap pointers
On macOS, BluetoothRemoteGattServiceMac, BluetoothRemoteGattCharacteristicMac,
and BluetoothRemoteGattDescriptorMac constructed GATT identifiers using Objective-C
format string stringWithFormat:@"%s-%p". Because macOS Chromium uses PartitionAlloc
Everywhere (PA-E), formatting %p embeds 64-bit virtual heap addresses into the identifier string.
When these strings are sent over Mojo IPC to the renderer process, a compromised
renderer could read these pointer addresses to map browser heap layout and bypass ASLR.
Replace %p with base::UnguessableToken::Create().ToString().c_str() to ensure
cryptographically unguessable, stateless, thread-safe uniqueness without leaking
browser heap layout. Also update operator<< logging to log GetIdentifier().
TAG=agy
CONV=60ab6f7d-f6e6-4bf5-8b14-067aefab4126
Bug: 500484520
Change-Id: Ic69106765f6a13c6746601321b50a13336f67412
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8025918
Reviewed-by: Matt Reynolds <mattreynolds@chromium.org>
Commit-Queue: Rob Pitkin <robpitkin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1661181}
---
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
index b2ba785..20a2cfe2 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
@@ -9,9 +9,11 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/notimplemented.h"
+#include "base/strings/strcat.h"
#include "base/strings/sys_string_conversions.h"
#import "base/task/single_thread_task_runner.h"
#include "base/task/single_thread_task_runner.h"
+#include "base/unguessable_token.h"
#include "device/bluetooth/bluetooth_device_mac.h"
#include "device/bluetooth/bluetooth_gatt_notify_session.h"
#include "device/bluetooth/bluetooth_low_energy_adapter_apple.h"
@@ -80,9 +82,8 @@
weak_ptr_factory_(this) {
uuid_ = BluetoothLowEnergyAdapterApple::BluetoothUUIDWithCBUUID(
[cb_characteristic_ UUID]);
- identifier_ = base::SysNSStringToUTF8(
- [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(),
- cb_characteristic_]);
+ identifier_ = base::StrCat({uuid_.canonical_value(), "-",
+ base::UnguessableToken::Create().ToString()});
}
BluetoothRemoteGattCharacteristicMac::~BluetoothRemoteGattCharacteristicMac() {
@@ -483,9 +484,7 @@
static_cast<const BluetoothRemoteGattServiceMac*>(
characteristic.GetService());
return out << "<BluetoothRemoteGattCharacteristicMac "
- << characteristic.GetUUID().canonical_value() << "/"
- << &characteristic
- << ", service: " << service_mac->GetUUID().canonical_value() << "/"
- << service_mac << ">";
+ << characteristic.GetIdentifier()
+ << ", service: " << service_mac->GetIdentifier() << ">";
}
} // namespace device.
diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm b/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm
index 169dab0..dbc25d7 100644
--- a/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm
+++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm
@@ -7,9 +7,11 @@
#import "base/apple/foundation_util.h"
#include "base/functional/bind.h"
#include "base/notimplemented.h"
+#include "base/strings/strcat.h"
#include "base/strings/sys_string_conversions.h"
#import "base/task/single_thread_task_runner.h"
#include "base/task/single_thread_task_runner.h"
+#include "base/unguessable_token.h"
#include "device/bluetooth/bluetooth_low_energy_adapter_apple.h"
#import "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h"
@@ -50,9 +52,8 @@
: gatt_characteristic_(characteristic), cb_descriptor_(descriptor) {
uuid_ = BluetoothLowEnergyAdapterApple::BluetoothUUIDWithCBUUID(
[cb_descriptor_ UUID]);
- identifier_ = base::SysNSStringToUTF8(
- [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(),
- cb_descriptor_]);
+ identifier_ = base::StrCat({uuid_.canonical_value(), "-",
+ base::UnguessableToken::Create().ToString()});
}
std::string BluetoothRemoteGattDescriptorMac::GetIdentifier() const {
@@ -188,10 +189,9 @@
static_cast<const BluetoothRemoteGattCharacteristicMac*>(
descriptor.GetCharacteristic());
return out << "<BluetoothRemoteGattDescriptorMac "
- << descriptor.GetUUID().canonical_value() << "/" << &descriptor
- << ", characteristic: "
- << characteristic_mac->GetUUID().canonical_value() << "/"
- << characteristic_mac << ">";
+ << descriptor.GetIdentifier()
+ << ", characteristic: " << characteristic_mac->GetIdentifier()
+ << ">";
}
} // namespace device.
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_mac.mm b/device/bluetooth/bluetooth_remote_gatt_service_mac.mm
index 1a51be0..81900c1 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service_mac.mm
+++ b/device/bluetooth/bluetooth_remote_gatt_service_mac.mm
@@ -12,7 +12,9 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/notimplemented.h"
+#include "base/strings/strcat.h"
#include "base/strings/sys_string_conversions.h"
+#include "base/unguessable_token.h"
#include "device/bluetooth/bluetooth_low_energy_adapter_apple.h"
#include "device/bluetooth/bluetooth_low_energy_device_mac.h"
#include "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h"
@@ -30,8 +32,8 @@
discovery_pending_count_(0) {
uuid_ =
BluetoothLowEnergyAdapterApple::BluetoothUUIDWithCBUUID([service_ UUID]);
- identifier_ = base::SysNSStringToUTF8([NSString
- stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(), service_]);
+ identifier_ = base::StrCat({uuid_.canonical_value(), "-",
+ base::UnguessableToken::Create().ToString()});
}
BluetoothRemoteGattServiceMac::~BluetoothRemoteGattServiceMac() {}
@@ -195,10 +197,8 @@
const BluetoothRemoteGattServiceMac& service) {
const BluetoothLowEnergyDeviceMac* bluetooth_device_mac_ =
static_cast<const BluetoothLowEnergyDeviceMac*>(service.GetDevice());
- return out << "<BluetoothRemoteGattServiceMac "
- << service.GetUUID().canonical_value() << "/" << &service
- << ", device: " << bluetooth_device_mac_->GetAddress() << "/"
- << bluetooth_device_mac_ << ">";
+ return out << "<BluetoothRemoteGattServiceMac " << service.GetIdentifier()
+ << ", device: " << bluetooth_device_mac_->GetAddress() << ">";
}
} // namespace device
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.
References
On This Page