Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in FoldableAPIs
DescriptionInsufficient validation of untrusted input in FoldableAPIs
ComponentFoldableAPIs
Bug ClassLogic Error
Tracker496088449
Fix commit829bf4ec033c (chromium/src) +9/-60
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-02

Changed Functions

FunctionChangeNotes
if
content/browser/devtools/protocol/emulation_handler.cc
modified
GetDevicePostureProvider
content/browser/renderer_host/render_widget_host_delegate.cc
modified
RenderFrameProxyHost
content/browser/renderer_host/render_widget_host_delegate.h
modified
RenderWidgetHostImpl
content/browser/renderer_host/render_widget_host_delegate.h
modified
DevicePostureProviderImpl
content/browser/renderer_host/render_widget_host_delegate.h
modified
RenderWidgetHostViewBase
content/browser/renderer_host/render_widget_host_delegate.h
modified
RenderViewHostDelegateView
content/browser/renderer_host/render_widget_host_delegate.h
modified
TextInputManager
content/browser/renderer_host/render_widget_host_delegate.h
modified
GetDevicePostureProvider
content/browser/web_contents/web_contents_impl.cc
modified

Files Changed

  • content/browser/device_posture/device_posture_provider_impl.h
  • content/browser/devtools/protocol/emulation_handler.cc
  • content/browser/renderer_host/render_widget_host_delegate.cc
  • content/browser/renderer_host/render_widget_host_delegate.h
  • content/browser/web_contents/web_contents_impl.cc
  • content/browser/web_contents/web_contents_impl.h
  • third_party/blink/public/mojom/device_posture/device_posture_provider.mojom
  • third_party/blink/renderer/core/frame/local_frame.cc
  • third_party/blink/renderer/core/frame/local_frame.h
  • third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
  • third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
From 829bf4ec033ca45078c880a193c73fa6c534c37c Mon Sep 17 00:00:00 2001
From: Menard, Alexis <alexis.menard@intel.com>
Date: Thu, 16 Apr 2026 17:16:22 -0700
Subject: [PATCH] device-posture: Remove posture override mechanism from mojo.

These interfaces were used by devtools/emulation through WPT
to override the device posture for testing purposes rather than
relying on actual device posture. We can rework this by keeping the overriding mechanism in content/browser only.

Bug: 496095145, 496088449
Change-Id: Ia27f971ea434c5e2328290ea7286b66f6cf6819b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7763896
Reviewed-by: Bo Liu <boliu@chromium.org>
Commit-Queue: Menard, Alexis <alexis.menard@intel.com>
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Reviewed-by: Dominic Farolino <dom@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1616212}
---

diff --git a/content/browser/device_posture/device_posture_provider_impl.h b/content/browser/device_posture/device_posture_provider_impl.h
index f4821ed..ce621efe 100644
--- a/content/browser/device_posture/device_posture_provider_impl.h
+++ b/content/browser/device_posture/device_posture_provider_impl.h
@@ -32,10 +32,9 @@
       mojo::PendingReceiver<blink::mojom::DevicePostureProvider> receiver);
   DevicePosturePlatformProvider* platform_provider() const;
 
-  // DevicePostureProvider implementation.
   CONTENT_EXPORT void OverrideDevicePostureForEmulation(
-      blink::mojom::DevicePostureType posture) override;
-  CONTENT_EXPORT void DisableDevicePostureOverrideForEmulation() override;
+      blink::mojom::DevicePostureType posture);
+  CONTENT_EXPORT void DisableDevicePostureOverrideForEmulation();
 
  private:
   // DevicePostureClient implementation.
diff --git a/content/browser/devtools/protocol/emulation_handler.cc b/content/browser/devtools/protocol/emulation_handler.cc
index d5d449a..276cf99 100644
--- a/content/browser/devtools/protocol/emulation_handler.cc
+++ b/content/browser/devtools/protocol/emulation_handler.cc
@@ -779,6 +779,7 @@
   if (device_posture) {
     params.device_posture =
         DevicePostureTypeFromString(device_posture->GetType()).value();
+    SetDevicePostureOverride(std::move(device_posture));
   }
 
   if (mobile ||
@@ -851,6 +852,7 @@
     return Response::Success();
 
   GetWebContents()->ClearDeviceEmulationSize();
+  ClearDevicePostureOverride();
   device_emulation_enabled_ = false;
   device_emulation_params_ = blink::DeviceEmulationParams();
   if (screen_orientation_lock_emulation_enabled_) {
diff --git a/content/browser/renderer_host/render_widget_host_delegate.cc b/content/browser/renderer_host/render_widget_host_delegate.cc
index 0311764..f180bdd 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -102,7 +102,7 @@
   return ui::mojom::WindowShowState::kDefault;
 }
 
-blink::mojom::DevicePostureProvider*
+DevicePostureProviderImpl*
 RenderWidgetHostDelegate::GetDevicePostureProvider() {
   return nullptr;
 }
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h
index 4dad6bba..e4c41fea 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -20,7 +20,6 @@
 #include "services/metrics/public/cpp/ukm_recorder.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
 #include "third_party/blink/public/common/page/drag_operation.h"
-#include "third_party/blink/public/mojom/device_posture/device_posture_provider.mojom.h"
 #include "third_party/blink/public/mojom/frame/lifecycle.mojom.h"
 #include "third_party/blink/public/mojom/input/input_handler.mojom-shared.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
@@ -56,6 +55,7 @@
 
 class RenderFrameProxyHost;
 class RenderWidgetHostImpl;
+class DevicePostureProviderImpl;
 class RenderWidgetHostViewBase;
 class RenderViewHostDelegateView;
 class TextInputManager;
@@ -238,7 +238,7 @@
   virtual ui::mojom::WindowShowState GetWindowShowState();
 
   // Returns the device posture provider tracking the device posture.
-  virtual blink::mojom::DevicePostureProvider* GetDevicePostureProvider();
+  virtual DevicePostureProviderImpl* GetDevicePostureProvider();
 
   // Returns whether the window can be resized or not. Defaults to true for
   // desktopOSs and false for mobileOSs.
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index ff27b82..b3480792 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -4939,8 +4939,7 @@
                        : ui::mojom::WindowShowState::kDefault;
 }
 
-blink::mojom::DevicePostureProvider*
-WebContentsImpl::GetDevicePostureProvider() {
+DevicePostureProviderImpl* WebContentsImpl::GetDevicePostureProvider() {
   return DevicePostureProviderImpl::GetOrCreate(this);
 }
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 757277f..368b9d4c 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -1185,7 +1185,7 @@
   // bool IsFullscreen() const override;
   blink::mojom::DisplayMode GetDisplayMode() const override;
   ui::mojom::WindowShowState GetWindowShowState() override;
-  blink::mojom::DevicePostureProvider* GetDevicePostureProvider() override;
+  DevicePostureProviderImpl* GetDevicePostureProvider() override;
   bool GetResizable() override;
   void LostPointerLock(RenderWidgetHostImpl* render_widget_host) override;
   bool HasPointerLock(RenderWidgetHostImpl* render_widget_host) override;
diff --git a/third_party/blink/public/mojom/device_posture/device_posture_provider.mojom b/third_party/blink/public/mojom/device_posture/device_posture_provider.mojom
index 365e2777..8884bbe7 100644
--- a/third_party/blink/public/mojom/device_posture/device_posture_provider.mojom
+++ b/third_party/blink/public/mojom/device_posture/device_posture_provider.mojom
@@ -20,11 +20,6 @@
   AddListenerAndGetCurrentPosture(
     pending_remote<DevicePostureClient> client)
       => (DevicePostureType posture);
-
-  // This is used by DevTools to emulate a device posture.
-  OverrideDevicePostureForEmulation(DevicePostureType posture);
-  // This is used by DevTools to disable emulation of a device posture.
-  DisableDevicePostureOverrideForEmulation();
 };
 
 // Interface that client of the DevicePostureProvider interface must implement
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index 54b76ad1..b1bf68e5 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1833,15 +1833,6 @@
   }
 }
 
-void LocalFrame::OverrideDevicePostureForEmulation(
-    mojom::blink::DevicePostureType device_posture_param) {
-  mojo_handler_->OverrideDevicePostureForEmulation(device_posture_param);
-}
-
-void LocalFrame::DisableDevicePostureOverrideForEmulation() {
-  mojo_handler_->DisableDevicePostureOverrideForEmulation();
-}
-
 mojom::blink::DevicePostureType LocalFrame::GetDevicePosture() {
   return mojo_handler_->GetDevicePosture();
 }
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 8669b41d..dffb6f5 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -455,9 +455,6 @@
       StyleEnvironmentVariables& vars,
       const std::vector<gfx::Rect>& viewport_segments);
 
-  void OverrideDevicePostureForEmulation(
-      mojom::blink::DevicePostureType device_posture_param);
-  void DisableDevicePostureOverrideForEmulation();
   mojom::blink::DevicePostureType GetDevicePosture();
 
   String SelectedText() const;
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
index fa8b198..72a0bd2c 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -433,16 +433,6 @@
   return current_device_posture_;
 }
 
-void LocalFrameMojoHandler::OverrideDevicePostureForEmulation(
-    mojom::blink::DevicePostureType device_posture_param) {
-  DevicePostureProvider()->OverrideDevicePostureForEmulation(
-      device_posture_param);
-}
-
-void LocalFrameMojoHandler::DisableDevicePostureOverrideForEmulation() {
-  DevicePostureProvider()->DisableDevicePostureOverrideForEmulation();
-}
-
 Page* LocalFrameMojoHandler::GetPage() const {
   return frame_->GetPage();
 }
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
index 35f0e927..31b6e33 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
Loading diff…

Original Bug Report

reported by vm...@google.com

Cross-origin device posture spoofing and DoS via OverrideDevicePostureForEmulation

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

Overview: The DevicePostureProvider Mojo interface lacks authorization checks for its DevTools emulation methods. A compromised renderer can spoof the device posture for all frames in a WebContents and block legitimate platform posture updates.

Affected files:

  • content/browser/device_posture/device_posture_provider_impl.cc
  • content/browser/browser_interface_binders.cc
  • third_party/blink/public/mojom/device_posture/device_posture_provider.mojom

Estimated timestamp from git blame: 2025-11-25

Summary

The DevicePostureProvider Mojo interface exposes methods intended for DevTools emulation: OverrideDevicePostureForEmulation and DisableDevicePostureOverrideForEmulation. However, the implementation in the browser process (DevicePostureProviderImpl) lacks any authorization checks. Because this provider is shared across the entire WebContents (tab), a compromised renderer (e.g., in a cross-origin iframe) can call these methods to spoof the device posture for the top-level page and all other frames in the tab. This allows a cross-origin state injection and a tab-scoped Denial of Service (DoS) against the Device Posture API.

Potential Root Cause

  1. Missing Authorization: In content/browser/device_posture/device_posture_provider_impl.cc, the OverrideDevicePostureForEmulation method accepts a posture type and unconditionally sets an internal is_posture_emulated_ flag. It does not check if the caller is privileged (e.g., DevTools) or if the request came from a potentially compromised renderer.
  2. Shared State (WebContents Scope): DevicePostureProviderImpl inherits from WebContentsUserData<DevicePostureProviderImpl>. This means there is only one instance of this provider per tab, shared among all frames (including cross-origin iframes).
  3. Unconditional Binding: The interface is bound in content/browser/browser_interface_binders.cc within PopulateBinderMapWithContext<RenderFrameHostImpl*>, making it accessible to any frame via the BrowserInterfaceBroker.

Suggested Attacker Steps

(Note: These are potential steps as a working Proof of Concept has not yet been developed and run by our setup.)

  1. Compromise Renderer: An attacker exploits a vulnerability to gain code execution in a renderer process, potentially one hosting a cross-origin iframe (attacker.com).
  2. Bind Interface: The compromised renderer uses the BrowserInterfaceBroker to request a binding to the blink::mojom::DevicePostureProvider Mojo interface.
  3. Trigger Emulation: The attacker sends an IPC message calling OverrideDevicePostureForEmulation(blink::mojom::DevicePostureType::kFolded) over their bound interface.
  4. State Injection: The browser process unconditionally sets is_posture_emulated_ = true and broadcasts the spoofed kFolded posture to all connected DevicePostureClient objects in the WebContents, including the top-level victim document.
  5. Achieve DoS: When the physical device’s posture actually changes (e.g., the user unfolds their phone), the platform provider calls DevicePostureProviderImpl::OnDevicePostureChanged. Because is_posture_emulated_ is true, the method early-returns and drops the legitimate update. All frames in the tab are now permanently stuck reflecting the attacker’s spoofed posture.

Suggested Fix

Separate the DevTools emulation methods from the DevicePostureProvider interface into a distinct, privileged Mojo interface (e.g., DevicePostureEmulationProvider) that is only accessible to trusted DevTools clients. Alternatively, implement robust authorization checks within DevicePostureProviderImpl::OverrideDevicePostureForEmulation to ensure the caller has the appropriate permissions to emulate device state.

Evaluated with Chrome root at commit: 0eb4855bda702feaaa8b899336664f97e3df88b8


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. Please feel free to reach out to me if you have concerns or feedback.

View on issue tracker