This is a master key that only works after the attacker is already inside the apartment building
CVE-2026-0021 is an Android Settings app confused-deputy bug in AppInfoBase.java that can bypass a cross-user permission check and let code on the device act across user boundaries. Google lists Android 14, 15, 16, and 16-qpr2 as affected in the March 2026 bulletin, and the public fix adds an explicit INTERACT_ACROSS_USERS_FULL permission check for the calling package on multi-pane devices; the patch level that addresses the bulletin is 2026-03-05 or later.
The vendor's HIGH 8.4 score reflects worst-case device impact once the bug is reached, but it overstates enterprise patch urgency. This is not an initial-access bug: the attacker needs local code execution on the handset first, the vulnerable path sits in the Settings app, the fix strongly suggests multi-pane / large-screen form factors are the meaningful exposure set, and there is no KEV listing, no exploitation note for this CVE, and extremely low EPSS.
4 steps from start to impact.
Land code on the device with a malicious APK (adb install / sideloaded app)
- Attacker can get an app or payload executed locally on the Android device
- Target is running Android 14, 15, 16, or 16-qpr2
- Managed fleets often block sideloading and restrict unknown sources
- Google Play Protect and enterprise app allow-listing reduce commodity delivery
- This is post-initial-access by definition because the CVSS attack vector is local
adb/developer-mode policy violations are the best coverage; perimeter scanners are irrelevant.Reach the exported Settings path (am start / intent abuse)
- The malicious app can invoke the relevant exported Settings activity or flow
- The device exposes the vulnerable Settings implementation from an unpatched OEM build
- OEM variation can change reachability
- The patch points to a narrower UI path than a broad framework-wide primitive
- Some enterprise profiles heavily constrain cross-app intent abuse
com.android.settings from third-party packages can catch this; standard vulnerability scanners usually cannot.Exploit the confused deputy in hasInteractAcrossUsersFullPermission
INTERACT_ACROSS_USERS_FULL, which is strong evidence that the old logic allowed Settings to act as the deputy on behalf of an unprivileged app.- Device is missing the March 2026 fix
- Target path is the multi-pane variant described by the public patch
- The bug appears tied to a specific UI/code path rather than a universally reachable daemon
- Large-screen / multi-pane exposure is a smaller subset than the entire Android fleet
Abuse cross-user access for profile or data boundary break
- Target device actually has another user/profile worth crossing into
- Attacker's objective benefits from cross-user access rather than simple single-user app execution
- Many handsets are single-user and do not present rich cross-user targets
- Blast radius is typically one device, one user set, one tenant boundary
adb and developer options — USB debugging and unmanaged developer mode make local app delivery and testing materially easier for an attacker or insider. Apply this as device-hardening hygiene on managed fleets; again, no mitigation SLA applies here, but it should be part of your standing baseline before the remediation deadline.- Perimeter scanning does nothing here; this is a local handset bug, not an exposed network service.
- WAF, reverse proxy, and IDS signatures are irrelevant because there is no inbound HTTP attack surface to filter.
- MFA does not address the vulnerable permission decision inside the local Settings code path.
The supporting signals.
| In-the-wild status | No current public exploitation signal. CISA KEV does not list it, and the CISA ADP SSVC entry exposed via OpenCVE marks exploitation as none. |
|---|---|
| Proof-of-concept availability | No public PoC located in primary sources. The public AOSP diff is enough for a capable Android researcher to reconstruct the bug path. |
| EPSS | 0.00003 from the user-supplied intel block; that is effectively floor-level exploit probability. Primary-source percentile was not validated during this review. |
| KEV status | Not KEV-listed as of this assessment. No CISA due date applies. |
| CVSS vector reality check | CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H means local, no privileges, no user interaction. The problem is that AV:L on Android usually implies a malicious app is already on the phone, which is a major real-world downgrade from internet-reachable bugs. |
| Affected versions | Google lists Android 14, 15, 16, and 16-qpr2 as affected in the March 2026 Android Security Bulletin and the CVE record. |
| Fixed versions | Device-side remediation is Android security patch level 2026-03-05 or later. In AOSP/OSV terms, the issue is fixed at branch SPL markers 14:2026-03-01, 15:2026-03-01, 16:2026-03-01, and 16-qpr2:2026-03-01, with OEM shipment typically surfaced as the March 2026-03-05 patch level. |
| Scanning / exposure data | Not internet-scannable. Shodan/Censys/FOFA/GreyNoise-style exposure metrics are largely non-applicable because this is a local handset bug in the Android Settings app, not a remotely exposed network service. |
| Disclosure timeline | Published 2026-03-02 in the Android Security Bulletin and CVE record; the bulletin was later updated through 2026-04-17. |
| Research / reporting | Public attribution is minimal. The fix is tied to Android bug A-430047417 and landed in the public platform/packages/apps/Settings repository. |
Sources.
Why this verdict
- Start from 8.4 HIGH, then cut for attacker position:
AV:Lon Android means the adversary already has code running on the device, usually via a malicious app or prior compromise. - Cut again for exposure population: the patch explicitly references permission checking on multi-pane devices, which points to tablets/foldables/large-screen paths rather than the entire Android phone fleet.
- Cut again for threat intel: no KEV, no public exploitation note for this CVE, no primary-source PoC, and a near-zero EPSS score all argue against emergency treatment.
Why not higher?
This should not stay HIGH because it does not give an attacker a path onto the device; it only helps after they already landed code locally. The blast radius is also usually limited to a single handset and its user/profile boundaries, not broad tenant or server compromise.
Why not lower?
I am not pushing it to LOW because cross-user boundary breaks on Android can still matter in enterprise work-profile and shared-user scenarios. If a malicious app is already present, the bug removes an important isolation boundary without requiring extra privileges or user clicks.
Crowdsourced verification payload.
Run this on an auditor workstation that has adb installed and USB or network debugging access to the target Android device. Invoke it as ./check-cve-2026-0021.sh <serial> for a specific device, for example ./check-cve-2026-0021.sh ZX1G22B7; no root is required, but adb shell getprop access is required.
#!/usr/bin/env bash
# check-cve-2026-0021.sh
# Conservative verifier for CVE-2026-0021 on Android devices via adb.
# Logic:
# - Affected Android branches: 14, 15, 16, 16-qpr2
# - Android bulletin says security patch level 2026-03-05 or later addresses all issues
# Output:
# PATCHED = device not in affected major versions, or SPL >= 2026-03-05
# VULNERABLE = affected major version and SPL < 2026-03-05
# UNKNOWN = cannot determine required properties / adb issues
# Exit codes:
# 0 PATCHED
# 1 VULNERABLE
# 2 UNKNOWN
set -u
SERIAL="${1:-}"
ADB_BIN="${ADB:-adb}"
FIXED_SPL="2026-03-05"
adb_cmd() {
if [[ -n "$SERIAL" ]]; then
"$ADB_BIN" -s "$SERIAL" "$@"
else
"$ADB_BIN" "$@"
fi
}
if ! command -v "$ADB_BIN" >/dev/null 2>&1; then
echo "UNKNOWN - adb not found in PATH"
exit 2
fi
if ! adb_cmd get-state >/dev/null 2>&1; then
echo "UNKNOWN - no reachable adb device"
exit 2
fi
ANDROID_RELEASE="$(adb_cmd shell getprop ro.build.version.release 2>/dev/null | tr -d '\r')"
ANDROID_CODENAME="$(adb_cmd shell getprop ro.build.version.codename 2>/dev/null | tr -d '\r')"
SPL="$(adb_cmd shell getprop ro.build.version.security_patch 2>/dev/null | tr -d '\r')"
BUILD_FINGERPRINT="$(adb_cmd shell getprop ro.build.fingerprint 2>/dev/null | tr -d '\r')"
if [[ -z "$ANDROID_RELEASE" || -z "$SPL" ]]; then
echo "UNKNOWN - unable to read Android release or security patch level"
exit 2
fi
# Normalize major release (e.g., 14, 15, 16)
MAJOR="${ANDROID_RELEASE%%.*}"
# Basic SPL format check YYYY-MM-DD
if [[ ! "$SPL" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "UNKNOWN - unexpected security patch level format: $SPL"
exit 2
fi
# Determine affected branch
AFFECTED=0
case "$MAJOR" in
14|15|16)
AFFECTED=1
;;
*)
AFFECTED=0
;;
esac
if [[ "$AFFECTED" -eq 0 ]]; then
echo "PATCHED - not in affected Android major versions (release=$ANDROID_RELEASE spl=$SPL)"
exit 0
fi
# Lexicographic compare is safe for YYYY-MM-DD strings
if [[ "$SPL" < "$FIXED_SPL" ]]; then
echo "VULNERABLE - affected Android release=$ANDROID_RELEASE spl=$SPL (< $FIXED_SPL); fingerprint=$BUILD_FINGERPRINT"
exit 1
fi
# Note: this does not validate the device's multi-pane exposure path or OEM backport details.
echo "PATCHED - affected Android release=$ANDROID_RELEASE but spl=$SPL (>= $FIXED_SPL); fingerprint=$BUILD_FINGERPRINT"
exit 0