Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInappropriate implementation in Chrome for iOS
DescriptionInappropriate implementation in Chrome for iOS
ComponentChrome for iOS
Bug ClassLogic Error
Tracker519202895
Fix commit616092aa5049 (chromium/src) +8/-3
CISA KEVNot listed
CreditedGoogle
Disclosed2026-07-29

Changed Functions

FunctionChangeNotes
if
ios/chrome/browser/autofill/form_input_accessory/coordinator/form_input_accessory_mediator.mm
modified

Files Changed

  • ios/chrome/browser/autofill/form_input_accessory/coordinator/form_input_accessory_mediator.mm
From 616092aa5049bd5ce4059a8c78f1f9d45c20a423 Mon Sep 17 00:00:00 2001
From: Alexis Hétu <[email protected]>
Date: Wed, 03 Jun 2026 19:39:37 -0700
Subject: [PATCH] [iOS] Prevent form_changed events from changing the KA's target web frame

This CL sets the last focused web frame ID only after the form_changed
early exit. This avoids overwriting the keyboard accessory's target web
frame ID with gestureless form_changed events.

Bug: 519202895
Change-Id: I19ec344eaffaa0f091a8a09aa4ae5d36cb0f8d0a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7893290
Reviewed-by: Leo Zhao <[email protected]>
Commit-Queue: Alexis Hétu <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1641415}
---

diff --git a/ios/chrome/browser/autofill/form_input_accessory/coordinator/form_input_accessory_mediator.mm b/ios/chrome/browser/autofill/form_input_accessory/coordinator/form_input_accessory_mediator.mm
index bd95433..a90b5178 100644
--- a/ios/chrome/browser/autofill/form_input_accessory/coordinator/form_input_accessory_mediator.mm
+++ b/ios/chrome/browser/autofill/form_input_accessory/coordinator/form_input_accessory_mediator.mm
@@ -486,6 +486,12 @@
     return;
   }
 
+  // Ignore form_changed events to prevent gestureless form changes from
+  // overwriting the active keyboard accessory's target web frame ID.
+  if (params.type == "form_changed") {
+    return;
+  }
+
   BOOL isDefaultViewEnabled =
       IsIOSKeyboardAccessoryDefaultViewEnabled() &&
       ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_PHONE;
@@ -505,9 +511,8 @@
     return;
   }
 
-  // Don't look for suggestions in the next events.
-  if (params.type == "blur" || params.type == "change" ||
-      params.type == "form_changed") {
+  // Skip retrieving suggestions for blur or change events.
+  if (params.type == "blur" || params.type == "change") {
     return;
   }
 
Loading diff…

Original Bug Report

reported by [email protected]

Potential cross-origin focus hijacking in iOS keyboard accessory via form_changed event

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 potential vulnerability in iOS Chrome allows a cross-origin iframe to silently hijack the keyboard accessory’s next/previous frame target. This occurs because the target frame state is updated before filtering out gestureless form change events. Consequently, tapping keyboard-accessory navigation controls can trigger unexpected focus redirection into an untrusted iframe.

Affected files:

  • ios/chrome/browser/autofill/form_input_accessory/coordinator/form_input_accessory_mediator.mm
  • ios/chrome/browser/autofill/model/form_input_accessory_view_handler.mm

Estimated timestamp from git blame: 2018-11-29

Summary

A potential focus-redirection vulnerability exists in iOS Google Chrome’s Keyboard Accessory Bar coordination. An attacker-controlled cross-origin iframe can silently overwrite the keyboard accessory’s target web frame ID using gestureless form_changed events. When the user subsequently taps the Next (▶) or Previous (◀) navigation arrows on the Keyboard Accessory Bar, the focus can be programmatically redirected to an input field inside the untrusted iframe.

Potential Root Cause

In ios/chrome/browser/autofill/form_input_accessory/coordinator/form_input_accessory_mediator.mm, the method -webState:didRegisterFormActivity:inFrame: updates the persistent target frame ID state before validating the event type or requiring a user gesture:

// ios/chrome/browser/autofill/form_input_accessory/coordinator/form_input_accessory_mediator.mm
self.validActivityForAccessoryView = YES;
[self setLastFocusFormActivityWebFrameID:frame]; // Overwrites the target frame ID unconditionally

if (isSelectOne && isDefaultViewEnabled) {
  [self.consumer showNavigationButtons];
  return;
}

// Don't look for suggestions in the next events.
if (params.type == "blur" || params.type == "change" ||
    params.type == "form_changed") {
  return; // Early return is evaluated AFTER the write
}

The call [self setLastFocusFormActivityWebFrameID:frame]; propagates directly to FormInputAccessoryViewHandler’s _lastFocusFormActivityWebFrameID ivar. Because the check for "form_changed" occurs after this write, any form_changed event received from a cross-origin iframe (which is dispatched automatically upon DOM mutations by form_handlers.ts without requiring a user gesture) will overwrite the target frame ID, while keeping the visible keyboard accessory suggestions and overall UI unchanged.

Proposed Attack Path

Note: Because our analysis is performed statically without dynamic execution capabilities, these represent potential/suggested steps to reproduce.

  1. A top-level page on origin A embeds an attacker-controlled cross-origin iframe B containing at least one focusable input element.
  2. The user taps an input field inside main frame A, initiating the native keyboard and custom accessory bar.
  3. Script running inside iframe B mutates its DOM (e.g., appends a form or element) to trigger a gestureless form_changed activity. This silently overwrites the native navigation target _lastFocusFormActivityWebFrameID with B’s frame ID.
  4. The user taps the native Next (▶) or Previous (◀) button on the custom Keyboard Accessory Bar.
  5. On configurations where the private API heuristic executeFormAssistAction: fails, Chrome falls back to evaluating isolated-world JS suggestion.selectNextElement in the frame resolved from _lastFocusFormActivityWebFrameID (which is now iframe B).
  6. Focus is programmatically shifted to the input field inside iframe B, bypassing standard WKWebView gesture gates.

Suggested Fix

To remediate this issue, the target frame ID state update should be moved after the event validation gates. For example:

// Move the state write to happen only after checking/filtering for appropriate types:
if (params.type == "blur" || params.type == "change" ||
    params.type == "form_changed") {
  return;
}

self.validActivityForAccessoryView = YES;
[self setLastFocusFormActivityWebFrameID:frame];

By ensuring that the target web frame ID is updated only for focus-registering events, the cross-origin hijack via background gestureless DOM mutations is prevented.

Evaluated with Chrome root at commit: 87214e6721f6c34afd9181b80769a24c0c601c50


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