CVE-2025-0083 AI-generated analysis
platform/frameworks/base (telecomm/java/android/telecom/StatusHints.java) and platform/packages/services/Telecomm (TelecomServiceImpl phone account icon validation)
Replaces the Uri.getEncodedUserInfo()-based cross-user check on content-URI icons in StatusHints and in TelecomServiceImpl (phone account registration) with a new StatusHints.getUserIdFromAuthority() helper. The helper parses the user id from Uri.getAuthority() and rejects any icon whose user id differs from the caller's, including the percent-encoded test forms and non-numeric prefixes.
Root cause
StatusHints (icon validation near line 150) and TelecomServiceImpl (icon check during phone account registration, near line 3150) both took the target user id of a TYPE_URI / TYPE_URI_ADAPTIVE_BITMAP icon from icon.getUri().getEncodedUserInfo(). When that value was null, the code assumed the URI pointed at the calling user and accepted the icon. Per the commit message, a URI formatted as `userId%` is not parsed properly this way, so the cross-user check could be bypassed. The new tests use authorities '10%40media' and '10%40play.ground'. The old code also called Integer.parseInt(encodedUser) without handling NumberFormatException.
How the fix works
- platform/frameworks/base 24e31767630f, StatusHints.java: adds a @hide public static helper getUserIdFromAuthority(String auth, int defaultUserId). It returns defaultUserId when auth is null or contains no '@'. Otherwise it Integer.parseInt()s the substring before lastIndexOf('@'). A NumberFormatException is caught and logged with Log.w, and UserHandle.USER_NULL is returned.
- Same commit, StatusHints icon validation: for TYPE_URI / TYPE_URI_ADAPTIVE_BITMAP icons it computes requestingUserId = getUserIdFromAuthority(icon.getUri().getAuthority(), callingUserId). It returns null (drops the icon) whenever callingUserId != requestingUserId.
- platform/packages/services/Telecomm e1a0858925cb, TelecomServiceImpl.java: imports android.telecom.StatusHints and replaces the getEncodedUserInfo()/parseInt block with callingUserId = UserHandle.getCallingUserId() and requestingUserId = StatusHints.getUserIdFromAuthority(icon.getUri().getAuthority(), callingUserId). If the two differ, it throws IllegalArgumentException("Attempting to register a phone account with an image icon belonging to another user.").
- Same Telecomm commit, TelecomServiceImplTest.testRegisterPhoneAccountImageIconCrossUser: adds two negative cases, encodedAuthority("10%40media") and Uri.parse("content://10%40play.ground"), both expected to be rejected, while "content://0@media/..." still succeeds.
Completeness
- Both validation sites named in the commit message (StatusHints and TelecomServiceImpl phone account registration) are updated and share one helper.
- A non-numeric prefix before '@' now yields USER_NULL and is rejected instead of throwing an uncaught NumberFormatException.
- The check still applies only to Icon.TYPE_URI and Icon.TYPE_URI_ADAPTIVE_BITMAP, as before.
- An authority with no '@' is treated as the calling user (defaultUserId), similar to the old behaviour when no user info was present.
- The material does not show whether other Telecom entry points accept content-URI icons without going through one of these two sites.
Behavior changes
- Registering a phone account with an icon whose authority names a user id different from the caller's (including the percent-encoded test forms) now throws IllegalArgumentException.
- Icons whose authority prefix before '@' is not an integer are now rejected: StatusHints drops the icon and logs a warning, and TelecomServiceImpl throws IllegalArgumentException. Previously both paths threw NumberFormatException.
- TelecomServiceImpl now gets the caller's user id from UserHandle.getCallingUserId() instead of UserHandle.getUserId(Binder.getCallingUid()).
- StatusHints gains a new @hide public static method getUserIdFromAuthority(String, int), which Telecomm depends on.
Per major
- Android 14: same fix: resolved in android-security-14.0.0_r18 via frameworks/base 24e31767630f (StatusHints.java) and Telecomm e1a0858925cb (TelecomServiceImpl.java plus test). At android-security-14.0.0_r29, 8/8 lines of the patched region are present.
- Android 15: same fix: resolved in android-security-15.0.0_r6 via Telecomm 685c2fc2f6b4, with the same Telecomm diff at different line offsets (hunk @@ -3421). At android-security-15.0.0_r17, 8/8 lines are present. The matching frameworks/base commit for 15 is not shown in the material.
- Android 16: not affected (not listed by the bulletin). At android-security-16.0.0_r8, 8/8 lines of the patched region are present.
- Android 17: not affected (not listed by the bulletin). At android-security-17.0.0_r1 the patched file telecomm/java/android/telecom/StatusHints.java is absent.
Unknowns
- Names of the enclosing methods in StatusHints.java and TelecomServiceImpl.java (the hunk headers show only the class).
- Exactly how Uri.getEncodedUserInfo() handled the `userId%` forms before the fix.
- Whether the two patched sites are the only places Telecom accepts caller-supplied content-URI icons.
- The frameworks/base StatusHints commit for Android 15.
- Where, if anywhere, the StatusHints icon validation lives in Android 17 (file absent at android-security-17.0.0_r1).
- Exact permission requirements on the real registerPhoneAccount path.