CVE-2025-26450 AI-generated analysis
platform/frameworks/base, input method framework (android.inputmethodservice, IME-side InputChannel receiver)
The IME-side input event receiver (IInputMethodSessionWrapper.ImeInputEventReceiver.onInputEvent) now checks any KeyEvent with Ctrl/Alt/Fn/Meta modifiers using InputManager.verifyInputEvent plus a 100 ms age check before dispatching it to the InputMethodSession, and drops events that fail.
Root cause
ImeInputEventReceiver.onInputEvent in core/java/android/inputmethodservice/IInputMethodSessionWrapper.java accepted InputEvents arriving on the IME's InputChannel and passed KeyEvents straight to mInputMethodSession.dispatchKeyEvent without checking that they came from the system. Per the commit message, a malicious app can inject fabricated InputEvents into the IME's FD. Modifier-key shortcuts handled by the IME (the message cites switching IME) could therefore be triggered by events that did not come from the system.
How the fix works
- core/java/android/inputmethodservice/IInputMethodSessionWrapper.java: the constructor now stores the Context in a new field mContext, so the receiver can obtain InputManager.
- IInputMethodSessionWrapper.ImeInputEventReceiver.onInputEvent: after the existing early-return path and before mPendingEvents.put/dispatch, if the event is a KeyEvent and hasKeyModifiers(keyEvent) is true, it fetches InputManager (Objects.requireNonNull) and computes age = SystemClock.uptimeMillis() - keyEvent.getEventTime(). If age >= KEY_EVENT_ALLOW_PERIOD_MS (100 ms) OR im.verifyInputEvent(keyEvent) == null, it logs a warning, calls finishInputEvent(event, false) and returns, so the event never reaches InputMethodSession.dispatchKeyEvent.
- New private helper ImeInputEventReceiver.hasKeyModifiers(KeyEvent): returns false if event.hasNoModifiers(), otherwise returns true when isCtrlPressed() || isAltPressed() || isFunctionPressed() || isMetaPressed().
- The dispatch code is otherwise unchanged, apart from switching to pattern-matching instanceof (event instanceof KeyEvent keyEvent).
Completeness
- Only KeyEvents for which hasKeyModifiers() is true (Ctrl, Alt, Function, Meta) are verified. KeyEvents with no modifiers, or with only other modifiers (e.g. Shift alone, for which hasKeyModifiers returns false), are still dispatched without verification.
- The MotionEvent branch of the same onInputEvent gets no verification.
- The check lives only in the IME-process receiver (IInputMethodSessionWrapper). Nothing in the diff changes how the InputChannel is created or who can write to it, so the fix filters on the receiving side rather than hardening the channel.
- The Android 16 variant (47414432d61c) is weaker in two visible ways. First, the drop condition uses && (age >= 100 ms AND unverified), so modifier KeyEvents younger than 100 ms are dispatched without HMAC verification. Second, hasKeyModifiers uses hasModifiers(META_CTRL_ON) || hasModifiers(META_ALT_ON) || hasModifiers(KeyEvent.KEYCODE_FUNCTION) (KEYCODE_FUNCTION is a key code constant, not a meta flag) and no longer checks Meta. The check is also gated by the verify_key_event aconfig flag. The 16 diff contains a TODO(b/331730488) noting that accessibility events are not yet handled.
- The 14 and 15 backports verify every modifier KeyEvent (|| condition) and are the stricter form.
Behavior changes
- Modifier (Ctrl/Alt/Fn/Meta) KeyEvents whose eventTime is 100 ms or more behind SystemClock.uptimeMillis() are dropped by the IME even if legitimate (14/15 variant).
- Modifier KeyEvents that InputManager.verifyInputEvent cannot verify are dropped with Log.w "Unverified or Invalid KeyEvent injected into IME. Dropping ..." and finished with handled=false. They are not delivered to the IME and are reported back as unhandled.
- Objects.requireNonNull on the InputManager service: a null service now throws instead of dispatching.
- Android 16 only: a new public API, onShouldVerifyKeyEvent(KeyEvent), on InputMethodService / AbstractInputMethodService (with a hidden default on InputMethodSession) lets an IME request verification for additional keys. A new fixed-read-only flag, android.view.inputmethod.verify_key_event, controls the whole check.
Per major
- Android 14: same fix: DO NOT MERGE cherry-pick f48bf9a2e7c7 in android-security-14.0.0_r21 (single file, || drop condition, isCtrlPressed/isAltPressed/isFunctionPressed/isMetaPressed, no flag); 8/8 patched lines present at android-security-14.0.0_r29.
- Android 15: same fix: identical DO NOT MERGE diff 4cafc04ee7db in android-security-15.0.0_r9; 8/8 lines present at android-security-15.0.0_r17.
- Android 16: adapted fix: Revert^2 "Verify KeyEvents in IME" 47414432d61c in android-16.0.0_r2. It is gated by the aconfig flag verify_key_event (is_fixed_read_only), adds the onShouldVerifyKeyEvent API to InputMethodService/AbstractInputMethodService/InputMethodSession and current.txt, and uses an && drop condition and a different hasKeyModifiers; 8/8 lines present at android-security-16.0.0_r8.
- Android 17: not affected per the bulletin; the patched region is present (8/8 lines) at android-security-17.0.0_r1.
Unknowns
- How an unprivileged app gets write access to the IME's InputChannel FD is not shown; only the commit message asserts it.
- Whether the 16 variant's && condition and KEYCODE_FUNCTION usage were intentional or later corrected is not shown in the material.
- Whether legitimate sources without a valid HMAC (e.g. accessibility or instrumentation injection) are affected by the drop is not shown, beyond the TODO about a11y events in the 16 diff.
- The Android 13 fix commit and the Android 13 code are not included, so whether the 14 diff applies cleanly to 13 is unknown.