Critical watch CVSS 8.8 chrome UAF 🔧 Commit mapped

Overview

Critical
Severity
8.8
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in XR
DescriptionUse after free in XR
ComponentXR
Bug ClassUAF
Action tierwatch — corruption primitive but gated (uncommon) — not default-reachable
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker497724498
Fix commitb173791bf402 (chromium/src) +8/-4
CWECWE-416 (Use-after-free)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedJihyeon Jeong (Compsec Lab, Seoul National University / Research Intern)
Reported2026-03-30 (per vendor advisory)
Fix landed2026-04-13 (public git)
Disclosed2026-04-15
Patch gap2 days — fix public in source before the advisory

Background

Dangling pointer / use-after-free (UAF)
a pointer that still refers to memory whose object has been freed or relocated, so dereferencing it reads or writes invalid memory.
`std::vector` reallocation
when a std::vector grows past its capacity, emplace_back/push_back moves its storage to a new buffer, invalidating every pointer, reference, and iterator into the old elements.
`OpenXrSpatialFrameworkManager`
the Chrome OpenXR device-layer component that builds an XrSpatialContextCreateInfoEXT from the capability configurations requested for a WebXR spatial session.

Root Cause Analysis

The context-creation routine in openxr_spatial_framework_manager.cc built two parallel vectors in a single loop: it emplace_backed an OpenXrSpatialCapabilityConfigurationBase into capability_configs and then immediately pushed capability_configs.back().GetAsBaseHeader() — a raw XrSpatialCapabilityConfigurationBaseHeaderEXT* pointing into that vector’s storage — into capability_config_ptrs. Because capability_configs had no reserved capacity, a later emplace_back could reallocate the vector’s backing buffer, leaving every previously collected pointer in capability_config_ptrs dangling at a freed address. Those stale pointers were then handed to the OpenXR runtime through XrSpatialContextCreateInfoEXT, i.e. the code read/passed freed memory.

The fix reserves the final capacity up front with capability_configs.reserve(capability_configuration.size()) and splits the work into two loops: the first fully populates capability_configs (no further reallocation possible after the reserve), and the second collects the element pointers only once all elements are stable.

Key insight
The single mistake was collecting interior pointers to std::vector elements while that same vector was still being grown, so reallocation invalidated them; the fix reserves exact capacity and defers pointer collection to a second loop after the vector is final.

Attack Path

  1. Start a spatial WebXR session Web content requests a WebXR session whose configuration maps to multiple OpenXR spatial capabilities, so capability_configuration holds more than one entry.
  2. Grow the configs vector OpenXrSpatialFrameworkManager loops over the entries, emplace_backing each into the zero-reserved capability_configs vector and recording a pointer to .back() in capability_config_ptrs.
  3. Trigger reallocation a subsequent emplace_back exceeds capacity and relocates capability_configs, leaving the earlier pointers in capability_config_ptrs dangling (inferred: whether this fires depends on how many capabilities are requested).
  4. Use freed memory the dangling pointers are passed into XrSpatialContextCreateInfoEXT and consumed when creating the spatial context, reading freed heap memory (inferred downstream consequences).

Impact Assessment

An attacker-influenced WebXR/OpenXR session can cause stale pointers into reallocated vector storage to be dereferenced inside the XR device code, a use-after-free the advisory rates critical. Reachability requires an OpenXR runtime/backend that supports the spatial framework extension and a session requesting enough spatial capabilities to force a reallocation — i.e. specific XR hardware/runtime rather than arbitrary stock web content. Any escalation beyond the memory error is not demonstrated by the diff and is (inferred).

Changed Functions

FunctionChangeNotes
for
device/vr/openxr/openxr_spatial_framework_manager.cc
modified

Files Changed

  • AUTHORS
  • device/vr/openxr/openxr_spatial_framework_manager.cc

Audit Directions

  • Pointer-into-container captured mid-growth
    search for code that stores .back(), &vec[i], or vec.data()-derived pointers/iterators inside a loop that continues to push_back/emplace_back/insert into the same container.
  • Parallel vectors built in lockstep
    flag patterns where one vector holds objects and a second holds pointers/references into the first; the pointer vector must be filled only after the object vector is fully sized (reserve or two-phase build).
  • FFI structs holding borrowed pointers
    audit OpenXR/graphics *CreateInfo structures that take arrays of raw pointers into local containers, ensuring the backing storage outlives the call and is never relocated between collection and use.
From b173791bf4026a6bb43124f7c5f46cfa4539c014 Mon Sep 17 00:00:00 2001
From: p0-tato <[email protected]>
Date: Mon, 13 Apr 2026 14:50:07 -0700
Subject: [PATCH] Fix dangling pointers in OpenXrSpatialFrameworkManager

Pointers to vector elements were collected during emplace_back,
which invalidates them on reallocation. Split into two loops
and reserve the correct capacity.

Bug: 497724498
Change-Id: I204534bc1bd1522fe03db86f03c2c3e0d285631c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7735242
Commit-Queue: Brian Sheedy <[email protected]>
Reviewed-by: Brian Sheedy <[email protected]>
Reviewed-by: Brandon Jones <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1613990}
---

diff --git a/AUTHORS b/AUTHORS
index 44daf5c..675d2c1 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -738,6 +738,7 @@
 Jihun Brent Kim <[email protected]>
 Jihwan Marc Kim <[email protected]>
 Jihye Hyun <[email protected]>
+Jihyeon Jeong <[email protected]>
 Jihyeon Lee <[email protected]>
 Jim Wu <[email protected]>
 Jin Yang <[email protected]>
diff --git a/device/vr/openxr/openxr_spatial_framework_manager.cc b/device/vr/openxr/openxr_spatial_framework_manager.cc
index 2fd3609..b6f82c5 100644
--- a/device/vr/openxr/openxr_spatial_framework_manager.cc
+++ b/device/vr/openxr/openxr_spatial_framework_manager.cc
@@ -74,12 +74,15 @@
   // to help abstract some of the details of creating the child structs, even
   // though at present we only have a configuration base.
   std::vector<OpenXrSpatialCapabilityConfigurationBase> capability_configs;
-  std::vector<XrSpatialCapabilityConfigurationBaseHeaderEXT*>
-      capability_config_ptrs;
+  capability_configs.reserve(capability_configuration.size());
   for (auto& [capability, components] : capability_configuration) {
     capability_configs.emplace_back(capability, components);
-    capability_config_ptrs.push_back(
-        capability_configs.back().GetAsBaseHeader());
+  }
+
+  std::vector<XrSpatialCapabilityConfigurationBaseHeaderEXT*>
+      capability_config_ptrs;
+  for (auto& config : capability_configs) {
+    capability_config_ptrs.push_back(config.GetAsBaseHeader());
   }
 
   XrSpatialContextCreateInfoEXT create_info = {
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.