Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in Reading Mode
DescriptionInsufficient validation of untrusted input in Reading Mode
ComponentReading Mode
Bug ClassLogic Error
Tracker507382702
Fix commite5cb6ad372e8 (chromium/src) +35/-4
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-02

Files Changed

  • chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
  • ui/accessibility/ax_tree_update.h
From e5cb6ad372e847d04a36419b7bb3d704bb1a7e1f Mon Sep 17 00:00:00 2001
From: Aaron Moss <[email protected]>
Date: Fri, 01 May 2026 13:28:33 -0700
Subject: [PATCH] [a11y] Harden Mojo deserializers for AXNodeIDs

Following up on crrev.com/c/7727677, ensure only valid AXNodeIDs are
accepted from the renderer in Mojo deserialization.

Bug: 507382702
Change-Id: I16ff363cc8f59e7d7fe92b937f2e07d37aeb3e7d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7795304
Commit-Queue: Aaron Moss <[email protected]>
Reviewed-by: David Tseng <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1624041}
---

diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
index fa4dfe5a..1859e46 100644
--- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
+++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
@@ -976,6 +976,11 @@
             << " which is not currently being observed";
     return;
   }
+  if (!ui::IsValidAXNodeIDFromRenderer(target_node_id)) {
+    VLOG(1) << "Received link click request with invalid target_node_id "
+            << target_node_id;
+    return;
+  }
   ui::AXActionData action_data;
   action_data.target_tree_id = target_tree_id;
   action_data.action = ax::mojom::Action::kDoDefault;
@@ -994,6 +999,11 @@
             << " which is not currently being observed";
     return;
   }
+  if (!ui::IsValidAXNodeIDFromRenderer(target_node_id)) {
+    VLOG(1) << "Received image data request with invalid target_node_id "
+            << target_node_id;
+    return;
+  }
   main_observer_->web_contents()->DownloadImageFromAxNode(
       target_tree_id, target_node_id,
       /*preferred_size=*/gfx::Size(),
@@ -1012,6 +1022,12 @@
     const std::vector<SkBitmap>& bitmaps,
     const std::vector<gfx::Size>& sizes) {
   CHECK(IsObservingTree(target_tree_id));
+  if (!ui::IsValidAXNodeIDFromRenderer(node_id)) {
+    VLOG(1) << "Received image data download notification with invalid node_id "
+            << node_id;
+    return;
+  }
+
   bool download_was_successful =
       network::IsSuccessfulStatus(http_status_code) || http_status_code == 0;
 
@@ -1038,6 +1054,11 @@
             << " which is not currently being observed";
     return;
   }
+  if (!ui::IsValidAXNodeIDFromRenderer(target_node_id)) {
+    VLOG(1) << "Received scroll request with invalid target_node_id "
+            << target_node_id;
+    return;
+  }
   ui::AXActionData action_data;
   action_data.target_tree_id = target_tree_id;
   action_data.target_node_id = target_node_id;
@@ -1127,6 +1148,16 @@
             << " which is not currently being observed";
     return;
   }
+  if (!ui::IsValidAXNodeIDFromRenderer(anchor_node_id)) {
+    VLOG(1) << "Received selection request with invalid anchor_node_id "
+            << anchor_node_id;
+    return;
+  }
+  if (!ui::IsValidAXNodeIDFromRenderer(focus_node_id)) {
+    VLOG(1) << "Received selection request with invalid focus_node_id "
+            << focus_node_id;
+    return;
+  }
   ui::AXActionData action_data;
   action_data.target_tree_id = target_tree_id;
   action_data.action = ax::mojom::Action::kSetSelection;
diff --git a/ui/accessibility/ax_tree_update.h b/ui/accessibility/ax_tree_update.h
index 9dad597e..9d99163be 100644
--- a/ui/accessibility/ax_tree_update.h
+++ b/ui/accessibility/ax_tree_update.h
@@ -67,10 +67,10 @@
   bool has_tree_data = false;
   AXTreeData tree_data;
 
-  // The id of a node to clear, before applying any updates,
-  // or 0 if no nodes should be cleared. Clearing a node means deleting
-  // all of its children and their descendants, but leaving that node in
-  // the tree. It's an error to clear a node but not subsequently update it
+  // The id of a node to clear, before applying any updates, or
+  // `kInvalidAXNodeID` if no nodes should be cleared. Clearing a node means
+  // deleting all of its children and their descendants, but leaving that node
+  // in the tree. It's an error to clear a node but not subsequently update it
   // as part of the tree update.
   AXNodeID node_id_to_clear = kInvalidAXNodeID;
 
Loading diff…

Original Bug Report

reported by [email protected]

AXNode ID Mojo deserialization hardening

Follow-up on b/498205735 to make sure other AXNode ID Mojo deserialization sites also check for valid IDs, to harden the browser against similar vulns.
View on issue tracker