Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient policy enforcement in WebXR
DescriptionInsufficient policy enforcement in WebXR
ComponentWebXR
Bug ClassLogic Error
Tracker497975477
Fix commitd9ccb8c1268f (chromium/src) +6/-2
CISA KEVNot listed
CreditedGoogle
Disclosed2026-05-12

Files Changed

  • device/vr/android/arcore/arcore_device.cc
From d9ccb8c1268ff5ff402688eff7c2514666d589e3 Mon Sep 17 00:00:00 2001
From: Brandon Jones <bajones@chromium.org>
Date: Wed, 01 Apr 2026 17:12:01 -0700
Subject: [PATCH] Gate front-facing WebXR on WebXRIncubations in browser proc

Updates the ARCore WebXR backend to only allow support for the
FRONT_FACING WebXR experimental feature if the WebXRIncubations
flag has been enabled. Previously the backend always indicated it
was allowed and the flag was handled in the renderer process.

Bug: 497975477
Change-Id: Ie4348988e330eb27c37bf8bb08c1756ea97c5a25
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7722806
Reviewed-by: Brian Sheedy <bsheedy@chromium.org>
Commit-Queue: Brandon Jones <bajones@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1608879}
---

diff --git a/device/vr/android/arcore/arcore_device.cc b/device/vr/android/arcore/arcore_device.cc
index 7d34e7c..3281756 100644
--- a/device/vr/android/arcore/arcore_device.cc
+++ b/device/vr/android/arcore/arcore_device.cc
@@ -43,8 +43,7 @@
                           mojom::XRSessionFeature::ANCHORS,
                           mojom::XRSessionFeature::DEPTH,
                           mojom::XRSessionFeature::IMAGE_TRACKING,
-                          mojom::XRSessionFeature::HIT_TEST,
-                          mojom::XRSessionFeature::FRONT_FACING}};
+                          mojom::XRSessionFeature::HIT_TEST}};
 
   return *kSupportedFeatures;
 }
@@ -94,6 +93,11 @@
     device_features.emplace_back(mojom::XRSessionFeature::WEBGPU);
   }
 
+  // Only support Front Facing mode if the WebXR incubations flag is enabled.
+  if (base::FeatureList::IsEnabled(features::kWebXRIncubations)) {
+    device_features.emplace_back(mojom::XRSessionFeature::FRONT_FACING);
+  }
+
   SetSupportedFeatures(device_features);
 }
 
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential unauthorized WebXR front-facing camera activation from compromised renderer

Project Fortify, an experimental security project, has identified the following potential security issue.

Overview: A compromised renderer can bypass Blink feature gates and request the experimental FRONT_FACING WebXR feature via a direct Mojo IPC call. The browser process fails to properly validate permissions or feature flags for this capability, treating it as automatically granted once the base AR permission is obtained. This allows an attacker to secretly activate the user’s selfie camera and extract derived sensor data without explicit consent.

Affected files:

  • content/browser/xr/service/xr_permission_results.cc
  • content/browser/xr/service/vr_service_impl.cc
  • device/vr/android/arcore/arcore_impl.cc
  • device/vr/android/arcore/arcore_device.cc
  • content/browser/xr/service/browser_xr_runtime_impl.cc

Estimated timestamp from git blame: 2026-01-13

Summary

A security vulnerability exists in the WebXR implementation where the experimental FRONT_FACING camera feature can be activated by a compromised renderer without proper permission checks or validation of experimental feature flags in the browser process. This allows a malicious site to activate the user’s front-facing (selfie) camera and obtain derived sensor data (such as light estimation and hit test results) without explicit consent for front-facing camera usage.

Technical Details

WebXR sessions can request various features, including FRONT_FACING (using the device’s front-facing camera). This feature is experimental and gated in the Blink renderer by RuntimeEnabledFeatures::WebXRFrontFacingEnabled (tied to the kWebXRIncubations flag in third_party/blink/renderer/modules/xr/xr_utils.cc:281).

However, if a compromised renderer bypasses the Blink-side checks and directly requests a session via the VRService::RequestSession Mojo interface, the browser process (content/browser/xr/service/vr_service_impl.cc) fails to re-validate whether this feature is enabled for the origin or require specific user consent.

The flaw occurs in two places in the browser process:

  1. Missing Feature Flag Validation: The browser process does not check the kWebXRIncubations base::Feature flag before granting the FRONT_FACING feature. It relies solely on whether the underlying device (e.g., ARCore) supports it (device/vr/android/arcore/arcore_device.cc:47 unconditionally lists it in kSupportedFeatures).
  2. Permission Logic Flaw: In content/browser/xr/service/vr_service_impl.cc, VRServiceImpl::OnPermissionResultsForFeatures validates requested features using XrPermissionResults::HasPermissionsFor. The implementation of XrPermissionResults::GetPermissionFor (content/browser/xr/service/xr_permission_results.cc:98) fails to map FRONT_FACING to a specific permission (returning std::nullopt). HasPermissionsFor incorrectly interprets this nullopt as ‘always granted’ (lines 57-60) once the base session permission (e.g., the AR permission) has been obtained.

The base AR permission prompt shown to users (“wants to create a 3D map of your surroundings and track camera position”) implies the use of the rear camera. It does not clearly communicate that the front-facing camera will be used, which has different privacy implications (tracking the user’s face).

When FRONT_FACING is granted through this bypass, the ARCore implementation (device/vr/android/arcore/arcore_impl.cc:846) configures the AR session to use AR_CAMERA_CONFIG_FACING_DIRECTION_FRONT via ArSession_setCameraConfig.

Potential Attack Steps

Note: These steps are suggested based on code analysis; a working proof of concept has not yet been executed.

  1. An attacker compromises a renderer process (e.g., via a V8 vulnerability).
  2. The compromised renderer ensures it has transient user activation (e.g., triggered concurrently with a user click).
  3. The renderer crafts a raw Mojo IPC message to device::mojom::VRService::RequestSession, requesting an immersive AR session (kImmersiveAr) and including FRONT_FACING (enum value 17) in the required_features array.
  4. The browser process receives the request and, since FRONT_FACING is supported by the device (ARCore), it proceeds without checking the kWebXRIncubations feature flag.
  5. The browser prompts the user for the base AR permission (or uses a previously granted permission).
  6. Because content::XrPermissionResults::GetPermissionFor returns std::nullopt for FRONT_FACING, the browser assumes no additional permissions are required and marks the feature as granted.
  7. The session is dispatched to the ARCore runtime, which configures the device to activate the front-facing (selfie) camera.
  8. The attacker uses other WebXR features (like HIT_TEST or LIGHT_ESTIMATION, which also return std::nullopt and are auto-granted) to extract derived environmental and facial tracking data from the user.

Impact

An attacker can activate the front-facing camera (visible to the user but not explicitly authorized for selfie use) and obtain derived sensor data (LIGHT_ESTIMATION spherical harmonics, HIT_TEST results against the environment/face) without the user’s explicit consent for front-facing camera usage. While raw camera pixels require the CAMERA_ACCESS feature (which correctly maps to VIDEO_CAPTURE), the unauthorized activation of the selfie camera and the collection of derived data violates user privacy boundaries.

Suggested Fix

  1. Map Permission: Update content::XrPermissionResults::GetPermissionFor (content/browser/xr/service/xr_permission_results.cc) to explicitly map FRONT_FACING to a relevant permission (e.g., blink::PermissionType::VIDEO_CAPTURE or a new specific permission) rather than returning std::nullopt.
  2. Validate Feature Flags: The browser process (e.g., in VRServiceImpl::RequestSession or XRRuntimeManagerImpl) should explicitly check base::Feature flags (like kWebXRIncubations) for experimental WebXR features before accepting them from a renderer, regardless of whether the underlying hardware runtime supports them.

Evaluated with Chrome root at commit: a9cbf6e8b275fe4147435aa905f3b7f5a656f5f0


Results from 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.

View on issue tracker