Chrome · Chrome for iOS
CVE-2026-13892
Logic Error in Chrome for iOS
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_injection_handler.mm |
modified |
Files Changed
ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_injection_handler.mm
Patch
From 2233714ad379ab3cd1487e5f4b513139a4484d25 Mon Sep 17 00:00:00 2001
From: Alexis Hétu <sugoi@chromium.org>
Date: Tue, 12 May 2026 16:14:33 -0700
Subject: [PATCH] [iOS] Pinned Target Web Frame During Asynchronous Field Injection
Pass the targeted frame ID explicitly to manual fill injection helper
methods. This ensures the target frame is pinned when the user selects
a suggestion, preventing race conditions or incorrect frame targeting
during asynchronous flows like reauthentication.
Bug: 501674841
Change-Id: I3472287814f882221312a1139ccc557ead156953
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7843312
Reviewed-by: Tommy Martino <tmartino@chromium.org>
Commit-Queue: Alexis Hétu <sugoi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1629616}
---
diff --git a/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_injection_handler.mm b/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_injection_handler.mm
index 3017ecc..e4b14d4 100644
--- a/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_injection_handler.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_injection_handler.mm
@@ -161,8 +161,11 @@
if ([self canUserInjectInPasswordField:passwordField
requiresHTTPS:requiresHTTPS]) {
+ // Store the current frame ID to make sure it isn't modified during the
+ // reauthentication process.
+ const std::string frameID = self.lastFocusedElementFrameIdentifier;
if (!passwordField) {
- [self fillLastSelectedFieldWithString:content];
+ [self fillLastSelectedFieldWithString:content frameId:frameID];
return;
}
@@ -173,7 +176,7 @@
if (result != ReauthenticationResult::kFailure) {
UmaHistogramEnumeration("IOS.Reauth.Password.ManualFallback",
ReauthenticationEvent::kSuccess);
- [weakSelf fillLastSelectedFieldWithString:content];
+ [weakSelf fillLastSelectedFieldWithString:content frameId:frameID];
} else {
UmaHistogramEnumeration("IOS.Reauth.Password.ManualFallback",
ReauthenticationEvent::kFailure);
@@ -187,7 +190,7 @@
} else {
UmaHistogramEnumeration("IOS.Reauth.Password.ManualFallback",
ReauthenticationEvent::kMissingPasscode);
- [self fillLastSelectedFieldWithString:content];
+ [self fillLastSelectedFieldWithString:content frameId:frameID];
}
}
}
@@ -263,9 +266,12 @@
return url::Origin();
}
web::WebState* activeWebState = _webStateList->GetActiveWebState();
- web::WebFrame* frame = activeWebState
- ? [self activeWebFrameFromWebState:activeWebState]
- : nullptr;
+ if (!activeWebState) {
+ return url::Origin();
+ }
+ web::WebFrame* frame =
+ [self activeWebFrameFromWebState:activeWebState
+ frameId:self.lastFocusedElementFrameIdentifier];
return frame ? frame->GetSecurityOrigin() : url::Origin();
}
@@ -292,17 +298,18 @@
#pragma mark - Private
-// Returns the last focused web frame associated with the given `webState`.
-- (web::WebFrame*)activeWebFrameFromWebState:(web::WebState*)webState {
+// Returns the web frame with `frameId` associated with the given `webState`.
+- (web::WebFrame*)activeWebFrameFromWebState:(web::WebState*)webState
+ frameId:(const std::string&)frameId {
autofill::AutofillJavaScriptFeature* feature =
autofill::AutofillJavaScriptFeature::GetInstance();
- return feature->GetWebFramesManager(webState)->GetFrameWithId(
- self.lastFocusedElementFrameIdentifier);
+ return feature->GetWebFramesManager(webState)->GetFrameWithId(frameId);
}
// Injects the passed string to the active field and jumps to the next field.
-- (void)fillLastSelectedFieldWithString:(NSString*)string {
+- (void)fillLastSelectedFieldWithString:(NSString*)string
+ frameId:(const std::string&)frameId {
if (!_webStateList) {
return;
}
@@ -312,7 +319,7 @@
}
web::WebFrame* activeWebFrame =
- [self activeWebFrameFromWebState:activeWebState];
+ [self activeWebFrameFromWebState:activeWebState frameId:frameId];
if (!activeWebFrame) {
return;
}
@@ -383,7 +390,9 @@
tabHelper->GetPasswordManager();
CHECK(passwordManager);
- web::WebFrame* frame = [self activeWebFrameFromWebState:webState];
+ web::WebFrame* frame =
+ [self activeWebFrameFromWebState:webState
+ frameId:self.lastFocusedElementFrameIdentifier];
if (!frame) {
return nil;
}
@@ -415,7 +424,9 @@
- (void)fillFormWithFillData:(FillData)fillData
webState:(web::WebState*)webState
formHelper:(PasswordFormHelper*)formHelper {
- web::WebFrame* activeWebFrame = [self activeWebFrameFromWebState:webState];
+ web::WebFrame* activeWebFrame =
+ [self activeWebFrameFromWebState:webState
+ frameId:self.lastFocusedElementFrameIdentifier];
if (!activeWebFrame) {
return;
}
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page