CVE-2025-26442 AI-generated analysis
platform/packages/apps/Settings, notification access confirmation (CDM flow), NotificationAccessConfirmationActivity
The Settings NotificationAccessConfirmationActivity now matches the requested notification listener against the full ComponentName of each resolved NotificationListenerService instead of only its package name, so the BIND_NOTIFICATION_LISTENER_SERVICE permission and intent-filter checks are applied to the exact requested service.
Root cause
In its setup code (the enclosing method is not shown), NotificationAccessConfirmationActivity validates the requested component (mComponentName) before it shows the notification-access confirmation dialog. It queries the services matching NotificationListenerService.SERVICE_INTERFACE for mUserId. It then loops over the results to check that the requested service declares android.permission.BIND_NOTIFICATION_LISTENER_SERVICE and appears in the NLS query result. The loop matched on service.serviceInfo.packageName.equals(mComponentName.getPackageName()), which compares only the package. The first service from that package in the result was the one checked. If it declared the permission, the loop broke with hasNLSIntentFilter = true, even when mComponentName referred to a different service in that package that does not itself declare the permission or the NLS intent filter.
How the fix works
- src/com/android/settings/notification/NotificationAccessConfirmationActivity.java, NLS validation loop: the loop condition changes from service.serviceInfo.packageName.equals(mComponentName.getPackageName()) to service.serviceInfo.getComponentName().equals(mComponentName). The permission check (requiredPermission.equals(service.serviceInfo.permission)) and the hasNLSIntentFilter result now apply only to the exact requested service. A component that is not in the NLS query result now reaches the existing 'lacks an intent-filter action' branch and finish().
- Same file, second hunk: trailing whitespace is removed after getWindow().setCloseOnTouchOutside(false). No functional change.
Completeness
- The fix covers the single validation loop in NotificationAccessConfirmationActivity. The other existing checks (non-null component and package name, component name length, package exists, label non-empty) are unchanged.
- A requested component that is not itself in the NLS query result is now rejected instead of being accepted through a sibling service.
- The material does not show onAllow() or the CDM caller side, so it does not show whether those have equivalent component-level validation.
Behavior changes
- Requests whose ComponentName is not itself in the NotificationListenerService query result, or which lack BIND_NOTIFICATION_LISTENER_SERVICE, are now rejected with finish() and a Slog.e, even if another service in the same package qualifies.
- No new strings, APIs or user-visible dialog changes. Legitimate requests for a correctly declared NLS component behave as before.
Per major
- Android 14: same fix: commit a395a242270c in android-security-14.0.0_r20 (cherry-pick of f5ed187ffb6f). At android-security-14.0.0_r29 the code context shows the getComponentName().equals(mComponentName) check in place.
- Android 15: same fix: commit 63f8849244d1 in android-security-15.0.0_r8, the same two-hunk diff shifted by one line.
- Android 16: not affected per the bulletin (not listed). 7/8 lines of the patched region are present at android-security-16.0.0_r8.
- Android 17: not affected per the bulletin (not listed). 7/8 lines of the patched region are present at android-security-17.0.0_r1.
Unknowns
- The Android 13 fix commit is not included in the material.
- The material does not show what onAllow() does with mComponentName or which caller (CDM) launches this activity. The full effect of the loose check is therefore inferred from the loop alone.
- The name of the method that contains the validation loop is not shown.
- The material does not explain why 7/8 rather than 8/8 lines of the patched region are reported present in the later tags.