CVE-2026-0013 AI-generated analysis
platform/packages/apps/DocumentsUI, picker (PickActivity / RootsFragment "more apps" entries)
PickActivity.setupLayout now calls setSelector(null) on the copied "more apps" intent so a caller-supplied selector can no longer redirect the activity launch DocumentsUI performs on the caller's behalf.
Root cause
In src/com/android/documentsui/picker/PickActivity.java, setupLayout(Intent intent) builds `moreApps = new Intent(intent)` from the incoming intent to offer other apps that can handle the request. It then clears only the explicit component (setComponent(null)) and the package (setPackage(null)), and leaves the intent's selector in place. The copied intent is passed to RootsFragment.show(..., /* intent= */ moreApps) and to CrossProfileUtils.getCrossProfileResolveInfo(getPackageManager(), moreApps). An Intent selector replaces the main intent for resolution purposes (general platform knowledge). So, as the commit message states, a selector carried on the original intent could make the launch of moreApps resolve to an arbitrary activity started with DocumentsUI's permissions.
How the fix works
- src/com/android/documentsui/picker/PickActivity.java:setupLayout adds `moreApps.setSelector(null);` immediately after `moreApps.setComponent(null); moreApps.setPackage(null);`. This happens before the copy is used for cross-profile resolution and before it is passed to RootsFragment.show.
- The fix is a single commit with a two-line change (one comment, one statement). No other files or logic are touched. Only the `moreApps` copy is changed; the original `intent` object is not modified.
Completeness
- The fix covers the one copy site in setupLayout. Both consumers of moreApps (CrossProfileUtils.getCrossProfileResolveInfo and RootsFragment.show) now receive an intent with the component, package and selector cleared.
- The selector is the only field added to the sanitized set. Other copied fields of the incoming intent (flags, extras, clip data, data URI, categories) still pass through unchanged. The material does not show whether any of those fields matter for security in the later launch.
- The material shows no other place in DocumentsUI that re-dispatches the incoming intent, so coverage beyond this function cannot be judged from the provided code.
Behavior changes
- Any selector on the intent that started PickActivity is now ignored when the list of alternative apps is built and when one of them is launched. Resolution now uses only the main intent fields.
- The diff adds no new error, result code or UI change.
Per major
- Android 14: Same fix: a48245c5bfa7 in android-security-14.0.0_r25 (cherry-pick of 32d6a7338dc3, Change-Id I3e2eeaab8990a20fe639a165630ed1773e47fb3c). All 6/6 lines of the patched region are present at android-security-14.0.0_r29. The context differs slightly: 14 calls the method mState.supportsCrossProfile().
- Android 15: Same fix: 15f898d5082a in android-security-15.0.0_r13, with an identical two-line insertion. The surrounding code uses the mState.supportsCrossProfile field and private-space logic. All 6/6 lines are present at android-security-15.0.0_r17.
- Android 16: Same fix: 9f2d3f09f8fd in android-security-16.0.0_r4, with an identical insertion and the same context as 15. All 6/6 lines are present at android-security-16.0.0_r8.
- Android 17: Not affected per the bulletin (not listed). At android-security-17.0.0_r1 only 4/6 lines of the patched region are present. The material does not show how the code differs there.
Unknowns
- Where exactly RootsFragment starts the moreApps intent, and whether user interaction (tapping an app entry) is required. The launch code is not in the material.
- Which apps can start PickActivity (manifest, export status, permissions).
- Whether any legitimate callers set a selector and are affected by it being dropped.
- Why Android 17 is not affected: whether the copy site was restructured or the selector was already cleared there.
- Whether other DocumentsUI entry points copy and re-launch the incoming intent in a similar way.