CVE-2026-10010
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifcontent/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java |
modified |
Files Changed
content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
Patch
From 253b422fbd1b50f3f44d22fb78a394f3e71dff10 Mon Sep 17 00:00:00 2001
From: Bo Liu <boliu@chromium.org>
Date: Mon, 18 May 2026 14:56:33 -0700
Subject: [PATCH] android: Unbind old ImeRenderWidgetHostImpl
Bug: 513995565
Change-Id: I562f024daffcd178c09c962096f580806b62e448
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7857409
Commit-Queue: Jinsuk Kim <jinsukkim@chromium.org>
Auto-Submit: Bo Liu <boliu@chromium.org>
Reviewed-by: Jinsuk Kim <jinsukkim@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1632423}
---
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
index f33ce62..239f57e 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
@@ -211,6 +211,8 @@
private @Nullable AutocorrectManager mAutocorrectManager;
+ private @Nullable ImeRenderWidgetHostImpl mBoundImeRenderWidgetHost;
+
/**
* {@ResultReceiver} passed in InputMethodManager#showSoftInput}. We need this to scroll to the
* editable node at the right timing, which is after input method window shows up.
@@ -262,7 +264,9 @@
public void onConnectionError(MojoException e) {}
@Override
- public void close() {}
+ public void close() {
+ mHandle.close();
+ }
}
/**
@@ -1098,6 +1102,11 @@
mWebContents.getStylusWritingHandler().onImeAdapterDestroyed();
}
+ if (mBoundImeRenderWidgetHost != null) {
+ mBoundImeRenderWidgetHost.close();
+ mBoundImeRenderWidgetHost = null;
+ }
+
WeakReference<ImeAdapterImpl> oldValue = sNativeHelperMap.remove(mNativeImeAdapterAndroid);
assert oldValue != null;
assert oldValue.get() == this;
@@ -1817,9 +1826,13 @@
*/
@CalledByNative
private void bindImeRenderHost(long nativeHandle) {
+ if (mBoundImeRenderWidgetHost != null) {
+ mBoundImeRenderWidgetHost.close();
+ mBoundImeRenderWidgetHost = null;
+ }
MessagePipeHandle handle =
CoreImpl.getInstance().acquireNativeHandle(nativeHandle).toMessagePipeHandle();
- new ImeRenderWidgetHostImpl(this, handle);
+ mBoundImeRenderWidgetHost = new ImeRenderWidgetHostImpl(this, handle);
}
/**
Original Bug Report
Potential cross-origin UI manipulation via orphaned ImeRenderWidgetHost receivers on Android
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 vulnerability in the Android IME implementation allows a compromised renderer to retain a Mojo connection to a WebContents after a cross-origin navigation. By sending messages through this orphaned connection, an attacker can manipulate accessibility magnification and IME state for the new origin. This issue stems from the failure to explicitly close old Mojo receivers when binding new ones during RenderFrameHost transitions.
Affected files:
content/browser/android/ime_adapter_android.cccontent/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.javacontent/public/android/java/src/org/chromium/content/browser/input/CursorAnchorInfoController.java
Estimated timestamp from git blame: Unknown (Google3 checkout)
Summary
In the Android implementation of Chromium, the ImeAdapterImpl (Java) and its native counterpart ImeAdapterAndroid (C++) are persistent objects tied to the lifetime of a WebContents. During cross-origin navigations, these objects survive and reconnect to the new renderer process. However, the Mojo receiver for the blink.mojom.ImeRenderWidgetHost interface is not explicitly closed when a new connection is established. This allows a compromised renderer from a previous origin to maintain its pipe and influence the IME and accessibility state of a subsequent, cross-origin victim site.
Technical Details
When the primary main frame navigates, ImeAdapterAndroid::SetImeRenderWidgetHost is called to establish a Mojo connection with the new renderer (content/browser/android/ime_adapter_android.cc:526). This function creates a new pipe and passes the receiver to the Java-side ImeAdapterImpl.bindImeRenderHost via JNI.
On the Java side, bindImeRenderHost instantiates a new ImeRenderWidgetHostImpl and binds it to the handle (content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java:1822). In the Chromium Mojo Java implementation, the Router (the underlying controller) for the binding must be explicitly closed to terminate the pipe. Because ImeAdapterImpl does not track or close previous Router instances, the pipe remains active as long as the renderer keeps it open. A native GlobalRef in WatcherImpl prevents the Java objects from being garbage collected while the pipe is alive.
Potential Impact
A compromised renderer can exploit this persistent connection to affect a victim site after navigation:
- Accessibility Magnification Hijacking: An attacker can call
UpdateCursorAnchorInfowith a maliciousinsertionMarker. If the user has accessibility magnification enabled (controlled by theAccessibilityMagnificationFollowsFocusfeature), the browser will callcontainerView.requestRectangleOnScreen()with attacker-supplied coordinates while the user is on the victim site (ImeAdapterImpl.java:1799). This causes the magnification viewport to jump to arbitrary locations. - IME UI Spoofing: The attacker can poison the
mInputCursorAnchorInfoinCursorAnchorInfoController.java. This state is used by the system IME to position suggestion popups and handwriting bounds, allowing the attacker to displace these UI elements on the victim page.
Suggested Attack Steps
- A user navigates to an attacker-controlled site, which is compromised or malicious.
- The attacker’s renderer stashes the
ImeRenderWidgetHostMojo remote. - The user navigates to a sensitive cross-origin site (e.g., a bank).
- The attacker’s renderer sends an
UpdateCursorAnchorInfomessage through the stashed remote. - The browser process, using the orphaned receiver, processes the message and updates the shared
ImeAdapterImplstate, triggering UI or accessibility changes on the victim page.
Recommended Fix
Modify ImeAdapterAndroid to maintain a handle to the blink.mojom.ImeRenderWidgetHost receiver (or its Java-side Router) and explicitly close the existing connection before binding a new one in SetImeRenderWidgetHost. Additionally, ImeRenderWidgetHostImpl in Java should implement logic to invalidate itself when the ImeAdapter is disconnected from its current RenderWidgetHostView.
Evaluated with Chrome root at commit: 1a8d40fc44df2088d5945c0bf53584038aa1614a
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.