CVE-2026-17972
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifios/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
Patch
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; }
Original Bug Report
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.mmios/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.
- A top-level page on origin A embeds an attacker-controlled cross-origin iframe B containing at least one focusable input element.
- The user taps an input field inside main frame A, initiating the native keyboard and custom accessory bar.
- Script running inside iframe B mutates its DOM (e.g., appends a form or element) to trigger a gestureless
form_changedactivity. This silently overwrites the native navigation target_lastFocusFormActivityWebFrameIDwith B’s frame ID. - The user taps the native Next (▶) or Previous (◀) button on the custom Keyboard Accessory Bar.
- On configurations where the private API heuristic
executeFormAssistAction:fails, Chrome falls back to evaluating isolated-world JSsuggestion.selectNextElementin the frame resolved from_lastFocusFormActivityWebFrameID(which is now iframe B). - 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.