Critical chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Critical
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input Accessibility
DescriptionInsufficient validation of untrusted input Accessibility
ComponentChromium
Bug ClassLogic Error
Tracker517332006
Fix commitb67efd3a537b (chromium/src) +2/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-11

Files Changed

  • ui/accessibility/platform/ax_platform_node_cocoa.mm
From b67efd3a537b800df6fc49d48089b241b7d6c843 Mon Sep 17 00:00:00 2001
From: Carlos Barrera <[email protected]>
Date: Thu, 04 Jun 2026 10:01:08 -0700
Subject: [PATCH] [a11y] Add NOTREACHED() to exhaustive switches in AXPlatformNodeCocoa

This change adds NOTREACHED() to the AXInvalid and AXPopupValue methods
in AXPlatformNodeCocoa. These methods use exhaustive switches over
enums, and adding NOTREACHED() prevents Fortify reports regarding
out-of-range integers and ensures the compiler recognizes all paths
are covered.

AX-Relnotes: n/a.
Bug: 517332006
Change-Id: Ie2c780582f6b40b84e81f422b7ebff32c1387b16
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7896760
Reviewed-by: David Tseng <[email protected]>
Commit-Queue: Carlos Marcelo Barrera Nolasco <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1641747}
---

diff --git a/ui/accessibility/platform/ax_platform_node_cocoa.mm b/ui/accessibility/platform/ax_platform_node_cocoa.mm
index 58b407e..375ff742 100644
--- a/ui/accessibility/platform/ax_platform_node_cocoa.mm
+++ b/ui/accessibility/platform/ax_platform_node_cocoa.mm
@@ -2219,6 +2219,7 @@
     case ax::mojom::InvalidState::kTrue:
       return @"true";
   }
+  NOTREACHED();
 }
 
 - (NSNumber*)AXIsMultiSelectable {
@@ -2281,6 +2282,7 @@
     case ax::mojom::HasPopup::kDialog:
       return @"dialog";
   }
+  NOTREACHED();
 }
 
 - (NSNumber*)AXRequired {
Loading diff…

Original Bug Report

reported by [email protected]

Potential Browser-Process UB in -[AXPlatformNodeCocoa AXInvalid] and AXPopupValue on macOS

Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: A compromised renderer can supply out-of-range integers for accessibility enum attributes due to a lack of Mojo validation. When accessed via macOS accessibility selectors, this can cause control flow to fall off the end of non-void Objective-C methods. This leads to undefined behavior and potential code execution in the unsandboxed browser process.

Affected files:

  • ui/accessibility/platform/ax_platform_node_cocoa.mm
  • ui/accessibility/mojom/ax_node_data_mojom_traits.cc
  • ui/accessibility/ax_node_data.cc

Estimated timestamp from git blame: 2021-11-09

Technical Analysis

1. Unvalidated Mojo Deserialization of Enum Attributes

In ui/accessibility/mojom/ax_node_data_mojom_traits.cc, the int_attributes map is deserialized directly without verifying that the integers correspond to valid enum ranges:

if (!data.ReadIntAttributes(&out->int_attributes.container())) {
  return false;
}

Because attributes like ax::mojom::InvalidState are defined as enums with limited valid values (e.g., kNone = 0, kFalse = 1, kTrue = 2), a compromised renderer can pass arbitrary out-of-range values (such as 3 or 0x10000000) for the ax::mojom::IntAttribute::kInvalidState key.

2. Enum Casting in the Browser Process

In ui/accessibility/ax_node_data.cc (line 591), AXNodeData::GetInvalidState() performs a static cast on the unvalidated attribute retrieved from the map:

ax::mojom::InvalidState AXNodeData::GetInvalidState() const {
  return static_cast<ax::mojom::InvalidState>(
      GetIntAttribute(ax::mojom::IntAttribute::kInvalidState));
}

3. Undefined Behavior in -[AXPlatformNodeCocoa AXInvalid]

In ui/accessibility/platform/ax_platform_node_cocoa.mm (line 2212), the macOS-specific selector switches on this state:

- (NSString*)AXInvalid {
  if (![self instanceActive])
    return nil;
  switch (_node->GetData().GetInvalidState()) {
    case ax::mojom::InvalidState::kNone:
    case ax::mojom::InvalidState::kFalse:
      return @"false";
    case ax::mojom::InvalidState::kTrue:
      return @"true";
  }
}

Because this switch is exhaustive relative to the enum definition, Clang assumes that all execution paths are covered and does not issue a -Wreturn-type warning or compilation error. However, at runtime, an out-of-range value (like 3) causes control flow to fall off the end of this non-void method.

In compiled Objective-C++ binaries, falling off a non-void method is undefined behavior. The compiler typically omits setting the return register (rax/x0), leaving a stale or garbage pointer. Since the caller (AppKit or VoiceOver dispatch) expects a valid NSString* return value, treating this garbage value as an object pointer and passing it to ARC reference management (e.g., objc_retainAutoreleasedReturnValue) or invoking selectors on it can lead to control flow hijack and potential RCE in the unsandboxed browser process.

4. Sibling Vulnerability: -[AXPlatformNodeCocoa AXPopupValue]

The exact same vulnerable pattern is present in -[AXPlatformNodeCocoa AXPopupValue] (line 2264) in the same file:

- (NSString*)AXPopupValue {
  if (![self instanceActive])
    return nil;
  int hasPopup = _node->GetIntAttribute(ax::mojom::IntAttribute::kHasPopup);
  switch (static_cast<ax::mojom::HasPopup>(hasPopup)) {
    case ax::mojom::HasPopup::kFalse:
      return @"false";
    case ax::mojom::HasPopup::kTrue:
      return @"true";
    case ax::mojom::HasPopup::kMenu:
      return @"menu";
    case ax::mojom::HasPopup::kListbox:
      return @"listbox";
    case ax::mojom::HasPopup::kTree:
      return @"tree";
    case ax::mojom::HasPopup::kGrid:
      return @"grid";
    case ax::mojom::HasPopup::kDialog:
      return @"dialog";
  }
}

This similarly falls off the end of the non-void method when an out-of-range integer is supplied for kHasPopup.


Potential Steps to Trigger (Hypothetical)

Note: These are potential steps based on source code analysis; our tooling has not run any code to verify execution.

  1. From a compromised Renderer process, access the blink::mojom::RenderAccessibilityHost interface.
  2. Construct an AXUpdatesAndEvents payload where an AXNodeData’s int_attributes map contains the key ax::mojom::IntAttribute::kInvalidState mapped to an out-of-range value (e.g., 3).
  3. Invoke the HandleAXEvents Mojo method with this payload.
  4. On macOS, trigger an accessibility query from a client (e.g., VoiceOver) that targets the modified node’s AXInvalid attribute.
  5. Observe a browser process crash or control flow hijack when AppKit attempts to process the returned garbage pointer.

Suggested Remediation

To safely handle unexpected enum values and prevent undefined behavior, do one of the following:

  1. Add a trailing return / default case: Ensure that all non-void platform methods have a fallback return value or a terminating NOTREACHED() if an invalid value is encountered:
- (NSString*)AXInvalid {
  if (![self instanceActive])
    return nil;
  switch (_node->GetData().GetInvalidState()) {
    case ax::mojom::InvalidState::kNone:
    case ax::mojom::InvalidState::kFalse:
      return @"false";
    case ax::mojom::InvalidState::kTrue:
      return @"true";
  }
  return nil; // Fallback to prevent falling off the end
}

Apply a similar fix to AXPopupValue and other sibling methods in ax_platform_node_cocoa.mm.

  1. Validate during Mojo Deserialization: Update ui/accessibility/mojom/ax_node_data_mojom_traits.cc to sanitize enum-typed integer values upon receipt, rejecting payloads that contain invalid out-of-range values.

Evaluated with Chrome root at commit: b1520ef4a76878853a31f0943b565e42060edec8


Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:

  • If you are familiar with the severity guidelines, you may adjust the severity.
  • If this is a false positive, and there’s no work to be done, please close as WAI.
  • If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.

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