CVE-2025-48532 AI-generated analysis
platform/packages/providers/MediaProvider, the MediaProvider.call() handler for MARK_MEDIA_AS_FAVORITE and its MediaStore client helper (apex/framework)
MediaProvider.markMediaAsFavorite no longer applies a caller-supplied ContentValues from the call extras. It now reads only a boolean IS_FAVORITE extra and builds the ContentValues itself, and the MediaStore client helper now sends that boolean instead of EXTRA_CONTENT_VALUES.
Root cause
In src/com/android/providers/media/MediaProvider.java, markMediaAsFavorite(Bundle extras) took the ContentValues directly from extras.getParcelable(MediaStore.EXTRA_CONTENT_VALUES), which is controlled by whoever invoked resolver.call(AUTHORITY, MARK_MEDIA_AS_FAVORITE, ...). It then called clearLocalCallingIdentity() and ran update(uri, values, null) for every URI in the ClipData. For callers other than the package manager, the only check was AccessChecker.hasAccessToCollection(..., forWrite=false), i.e. read access to the collection. The values were not limited to the IS_FAVORITE column, so columns other than is_favorite could be written to media rows under the provider's cleared identity. The commit message says: "The content values retrieved from extras in the MediaProvider can have values preset by the calling app and can affect other fields set."
How the fix works
- src/com/android/providers/media/MediaProvider.java:markMediaAsFavorite: no longer reads MediaStore.EXTRA_CONTENT_VALUES from the extras. Instead it reads `final boolean areFavorites = extras.getBoolean(MediaColumns.IS_FAVORITE)`. After the existing per-URI access check it builds a fresh ContentValues that contains only MediaColumns.IS_FAVORITE, set to 1 or 0. That provider-built ContentValues is what goes to update(uri, values, null) inside the clearLocalCallingIdentity()/restoreLocalCallingIdentity(token) block, so no caller-chosen column can reach update().
- apex/framework/java/android/provider/MediaStore.java (the helper that issues MARK_MEDIA_AS_FAVORITE, around line 1710): no longer builds the ContentValues, and replaces `extras.putParcelable(EXTRA_CONTENT_VALUES, values)` with `extras.putBoolean(MediaColumns.IS_FAVORITE, areFavorites)` to match the new provider-side contract. ClipData handling (EXTRA_CLIP_DATA) is unchanged.
Completeness
- Covers the MARK_MEDIA_AS_FAVORITE call path: the provider ignores any EXTRA_CONTENT_VALUES a caller still puts in the extras, and only is_favorite can be written through this method.
- The existing access check in markMediaAsFavorite is unchanged. Callers other than the package manager still only need to pass AccessChecker.hasAccessToCollection(..., forWrite=false) (read access) before the provider performs the update with its own identity. The fix narrows what is written, not who can trigger it.
- In the Android 16 code, MediaStore.createRequest(resolver, method, uris, values) still forwards caller-supplied ContentValues as EXTRA_CONTENT_VALUES to resolver.call(AUTHORITY, method, ...), where MediaProvider.getResultForCreateOperationsRequest passes them to createRequest(method, extras). That path returns a PendingIntent, and how it processes the values is not shown in the material, so whether it has a similar issue cannot be judged from the material.
Behavior changes
- The wire format of the MARK_MEDIA_AS_FAVORITE call changed: the provider now expects a boolean extra keyed by MediaColumns.IS_FAVORITE and no longer reads EXTRA_CONTENT_VALUES. A client that sends only EXTRA_CONTENT_VALUES will have its items marked not favorite (getBoolean defaults to false) instead of having its values applied.
- Only the is_favorite column can be changed through this method. Any other columns in a supplied ContentValues are silently dropped and no new error is raised.
Per major
- Android 14: Not affected per the bulletin (not listed). At android-security-14.0.0_r29, 7/8 lines of the patched region are present. The exact state of that branch is not shown.
- Android 15: Not affected per the bulletin (not listed). At android-security-15.0.0_r17, 7/8 lines of the patched region are present. The exact state of that branch is not shown.
- Android 16: Same fix: commit a6fcb52734f2 in android-security-16.0.0_r1 (cherry-pick of the internal change, Change-Id I0227139b0a04efcb7456557fbf2d47996c017bad). 8/8 lines of the patched region are present at android-security-16.0.0_r8.
- Android 17: Not affected per the bulletin (not listed). 8/8 lines of the patched region are present at android-security-17.0.0_r1.
Unknowns
- Which columns or fields a caller could affect through the old path, and the impact beyond the bulletin's High EoP rating.
- Whether arbitrary third-party apps can call MARK_MEDIA_AS_FAVORITE, or whether it is gated elsewhere in MediaProvider.call().
- Why Android 14 and 15 are listed as not affected even though the markMediaAsFavorite region exists there (7/8 lines present). The material does not show the state of those branches before the fix.
- How MediaProvider.createRequest(method, extras) handles caller-supplied EXTRA_CONTENT_VALUES on the createRequest path.
- Whether the patch applies cleanly to customized or older trees.