CVE-2026-0024 AI-generated analysis
platform/packages/providers/MediaProvider, MediaProvider.java (ContentResolver open path / location redaction)
MediaProvider's redaction decision for files opened via ContentResolver now also considers the UID passed in MediaStore.EXTRA_MEDIA_CAPABILITIES_UID, so media opened by a picker on behalf of an app lacking ACCESS_MEDIA_LOCATION gets location metadata redacted.
Root cause
isRedactionNeededForOpenViaContentResolver(Uri redactedUri, String ownerPackageName, File file) never looked at the opts Bundle. In the code shown, its decision rests on the redacted-URI flag and on whether the direct caller (getCallingPackageOrSelf()) owns the file. The remainder of the method is not shown in the material. When a picker (SAF, per the commit message) opens a media file on behalf of another app and supplies that app's UID in MediaStore.EXTRA_MEDIA_CAPABILITIES_UID, that UID's permissions were not considered. Per the commit message, this let an app bypass ACCESS_MEDIA_LOCATION and get unredacted location data.
How the fix works
- src/com/android/providers/media/MediaProvider.java: the open helper that computes redactionNeeded (code context around line 8910 in android-security-14.0.0_r29) now passes its opts Bundle to isRedactionNeededForOpenViaContentResolver(redactedUri, ownerPackageName, file, opts).
- src/com/android/providers/media/MediaProvider.java:isRedactionNeededForOpenViaContentResolver gains a Bundle opts parameter. The new check comes after the existing 'redactedUri != null -> true' check and before the owner check. If opts is non-null and opts.getInt(MediaStore.EXTRA_MEDIA_CAPABILITIES_UID) > 0, it builds LocalCallingIdentity.fromExternal(getContext(), mUserCache, mediaCapabilitiesUid, null, null) and returns true (redact) if that identity hasPermission(PERMISSION_IS_REDACTION_NEEDED).
- If the capabilities UID does not require redaction, the method falls through to the pre-existing logic, starting with the owner check. In effect, the on-behalf-of UID can now force redaction but cannot remove it.
Completeness
- Covers only opens that go through isRedactionNeededForOpenViaContentResolver with EXTRA_MEDIA_CAPABILITIES_UID present in opts. The on-behalf-of UID is honored only when the intermediary actually supplies it (the UID must be > 0).
- The new check sits after the redactedUri shortcut and before the owner check, so a file owned by the direct caller is now redacted when the capabilities UID requires it.
- The existing requireOriginal check downstream (MediaStore.getRequireOriginal(uri) together with redactionNeeded) now also fires for the capabilities-UID case and throws UnsupportedOperationException.
- Other redaction decision paths (e.g. FUSE-based opens) are not touched by this diff. The material does not show whether they already handle an on-behalf-of UID.
Behavior changes
- Opens that carry MediaStore.EXTRA_MEDIA_CAPABILITIES_UID for a UID where PERMISSION_IS_REDACTION_NEEDED holds now return a redacted file, even when the direct caller owns the file.
- For such opens with requireOriginal set on the URI, the call now fails with UnsupportedOperationException ('Caller must hold ACCESS_MEDIA_LOCATION permission to access original').
- An extra LocalCallingIdentity.fromExternal lookup is performed per open when the extra is present.
Per major
- Android 14: same fix: commit 50387ce9d85a in android-security-14.0.0_r25, identical logic (surrounding code uses RedactionInfo-based ranges). At android-security-14.0.0_r29, 6/8 lines of the patched region are present, and the code context shows opts passed at the call site.
- Android 15: same fix: commit 77f9bd12a6ed in android-security-15.0.0_r13, identical hunks at different line offsets (surrounding code uses RedactionUtils.getRedactionRanges). 6/8 lines of the patched region are present at android-security-15.0.0_r17.
- Android 16: same fix: commit 69a25763cdb4 in android-security-16.0.0_r4, identical hunks. 6/8 lines of the patched region are present at android-security-16.0.0_r8.
- Android 17: not affected per the bulletin. Only 4/8 lines of the patched region are present at android-security-17.0.0_r1, so the code there differs, and the material does not show how it is handled.
Unknowns
- The exact name of the enclosing open helper is not shown in the material (only the class-level hunk header).
- The full pre-fix logic of isRedactionNeededForOpenViaContentResolver after the owner check is not shown.
- Whether other open paths (e.g. FUSE) already respect the capabilities UID is not shown.
- Why the Android 17 region only partially matches, and how 17 handles the on-behalf-of UID, is not shown.
- Test coverage: the commit lists 'Test: manual' only.