Like leaving the security camera feed unlocked — but only in one building that almost nobody works in yet
CVE-2026-0047 is a missing permission check in ActivityManagerService.dumpBitmapsProto() on Android 16 QPR2 (Baklava). Any installed app — requiring zero declared permissions and zero user interaction — can invoke Binder transaction code #117 to dump protobuf-wrapped PNG bitmaps of every running app's UI. The PoC from Mobile Hacking Lab demonstrated exfiltration of 63 valid PNGs (679 KB) from a single emulator session. Affected versions are Android 16 QPR2 Beta 1–3 and any QPR2 build with a security patch level before 2026-03-01. The fix landed in the March 2026 Android Security Bulletin (patch level 2026-03-05).
Google's vendor severity of HIGH / 8.4 overstates real-world risk for enterprise defenders. The CVSS vector claims C:H / I:H / A:H, but the demonstrated impact is purely a confidentiality issue — stealing screen bitmaps. There is no integrity write and no denial-of-service path documented or reproduced. A more honest vector would be AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N (CVSS 6.2). Layer on that the attack requires installing a malicious app on a single device running a single Android version that shipped barely three months before the patch dropped, and the real-world severity compresses further. EPSS agrees: 0.14%, 3rd percentile. No KEV listing. No confirmed in-the-wild exploitation. For a 10,000-host fleet, the overlap between 'managed Android devices' and 'running unpatched Android 16 QPR2' is almost certainly single digits.
4 steps from start to impact.
Craft a zero-permission APK
activity system service. No special signing, no platform key, no sharedUserId — a stock debug-signed APK suffices. The entire exploit payload fits in a single Activity or BroadcastReceiver.- Android development environment
- Knowledge of Binder transaction code #117
- Any competent mobile security researcher can do this, but turning it into a campaign requires a delivery mechanism
IBinder.transact() calls targeting system service transaction codes.Deliver APK to target device
- Victim device running Android 16 QPR2 with patch level < 2026-03-01
- App installation succeeds (sideloading enabled or Play Store evasion)
- Google Play Protect on-device scanning
- Enterprise MDM sideloading restrictions
- Play Store automated review pipeline
- Very small target population (QPR2-only)
Invoke dumpBitmapsProto via Binder
activity service IBinder handle via ServiceManager.getService("activity"). It constructs a Parcel containing the IActivityManager interface token, a ParcelFileDescriptor pipe, target process arrays, and a PNG format specifier, then calls transact(117, ...). Because dumpBitmapsProto() never calls enforceCallingOrSelfPermission(DUMP), the call succeeds from any UID.- App is running on a vulnerable Android 16 QPR2 build
- ActivityManagerService is reachable (always true on a booted device)
- The method will throw a NullPointerException if arguments are malformed, but the PoC handles this correctly
- SELinux policy does not block this specific Binder transaction in default QPR2 policy
Extract and exfiltrate bitmaps
89 50 4E 47) and IEND trailers, isolates individual images, and exfiltrates them via HTTPS POST, DNS tunneling, or local storage for later retrieval. Stolen bitmaps may contain credentials, chat messages, banking screens, or 2FA codes visible at capture time.- Other apps are actively rendering UI (foreground or recent tasks)
- Network access for exfiltration (or physical retrieval)
- Data is bitmaps, not structured text — attacker needs OCR or manual review to extract credentials
- Volume of data is moderate (~680 KB per dump) but not continuous streaming
- Network exfiltration can be detected by MTD or enterprise proxy
DISALLOW_INSTALL_UNKNOWN_SOURCES restriction is applied across managed Android profiles. This eliminates the primary delivery mechanism for a zero-permission exploit APK. On managed devices this is typically already set; verify it covers personal-side BYOD profiles as well.ro.build.version.sdk matching Android 16 QPR2 AND ro.build.version.security_patch < 2026-03-01. Flag and prioritize these for OTA update. Given the patch is 7 months old, any remaining devices likely have stale update policies.- Network segmentation / firewall rules — The vulnerability is a local app-to-system-service Binder call. Network controls cannot prevent on-device exploitation. They only affect exfiltration, and the attacker has many covert channels.
- VPN or zero-trust network access — Same reasoning. The exploit never touches the network until exfiltration. ZTNA protects network resources, not on-device system service calls.
- Android Work Profile container isolation — The vulnerable
ActivityManagerServiceis a system-level service accessible from both personal and work profiles. Work profile isolation does not prevent a personal-side app from invokingdumpBitmapsProto(), and the dump may include bitmaps from work-profile apps in recent tasks.
The supporting signals.
| In-the-wild exploitation | None confirmed. Not listed in CISA KEV. No reports from Google TAG, Lookout, or Zimperium of active campaigns. The March 2026 bulletin flagged CVE-2026-21385 as under targeted exploitation — *not* this CVE. |
|---|---|
| Proof-of-concept | Public PoC available. mobilehackinglab/CVE-2026-0047-poc on GitHub — fully functional, extracts 63 PNGs from a Baklava emulator. Educational reproduction by Mobile Hacking Lab. |
| EPSS | 0.00138 (0.14%) — 3rd percentile. Exploit Prediction Scoring System rates this as extremely unlikely to be exploited in the next 30 days. |
| KEV status | Not listed. No CISA Known Exploited Vulnerabilities entry as of 2026-09-27. |
| CVSS vector | CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H — vendor-assigned. The I:H and A:H components are not supported by the demonstrated exploit, which is read-only bitmap exfiltration. A realistic re-vector would be AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N (6.2). |
| Affected versions | Android 16 QPR2 (Baklava) — Beta 1, Beta 2, Beta 3, and GA builds with security patch level < 2026-03-01. No other Android versions affected. |
| Fixed version | Security patch level 2026-03-05 or later. Fix committed to AOSP; Pixel devices received OTA in March 2026. OEM rollout varies. |
| Scanning / exposure | Not applicable for network scanning — this is a local Android vulnerability. Enterprise MDM inventory queries (ro.build.version.security_patch) are the detection vector. No Shodan/Censys/GreyNoise relevance. |
| Disclosure date | 2026-03-02 — published in Android Security Bulletin ASB-A-465136263. |
| Researcher | Discovered via Android security research; PoC independently reproduced by Mobile Hacking Lab with full patch-diff analysis and Binder transaction reverse engineering. |
Sources.
Why this verdict
- Local-only attack vector with app-install prerequisite: The attacker must install a malicious APK on the target device. In enterprise MDM environments with sideloading disabled, Play Protect enabled, and app whitelisting enforced, this prerequisite has very high friction. This is not remotely exploitable.
- Scoped to a single Android version: Only Android 16 QPR2 is affected. As of September 2026, Android 16 holds ~25% market share, but QPR2 is a subset predominantly on Pixel and select OEM devices. The overlap with enterprise-managed devices running *unpatched* QPR2 is negligible seven months post-patch.
- Overstated CVSS impact metrics: The vendor vector claims C:H/I:H/A:H, but the demonstrated exploit is read-only bitmap exfiltration — a confidentiality-only impact. No integrity modification or availability degradation has been shown. Adjusting to C:H/I:N/A:N drops the base score from 8.4 to 6.2 before friction adjustments.
- No exploitation signals: EPSS is 0.14% (3rd percentile), not KEV-listed, no TAG or threat-intel reports of in-the-wild use. The only CVE under active exploitation in the same bulletin was CVE-2026-21385.
- Role multiplier: Android devices occupy endpoint/workstation-equivalent roles — not identity infrastructure, hypervisor, CI/CD, or network edge. The worst-case high-value scenario is stealing screen bitmaps from an executive's phone showing sensitive content. The blast radius is single device → single user's visible UI state. This does not reach domain-takeover, fleet-compromise, or supply-chain-scale impact. No floor override applies.
Why not higher?
The public PoC is functional and the zero-permission / zero-interaction exploitation is genuinely elegant. However, the attack requires local app installation on a specific Android version, the impact is confidentiality-only (bitmap theft, not code execution or persistence), and the patch has been available for seven months. There is no credible path from this vulnerability to fleet-wide compromise, lateral movement, or identity-plane impact. Upgrading to HIGH would require either confirmed in-the-wild exploitation or a demonstrated integrity/availability impact chain.
Why not lower?
A working zero-permission PoC that exfiltrates screenshots from every running app with no user interaction is not trivial. On an unpatched device without MDM controls, exploitation is deterministic and reliable. The confidentiality impact against a targeted individual (executive, journalist, activist) could be severe. Dropping to LOW would understate the risk for organizations with unmanaged BYOD Android devices on QPR2.
Crowdsourced verification payload.
Run this script on a workstation with adb connected to the target Android device (USB debugging enabled). Requires adb shell access. Example: bash check_cve_2026_0047.sh. No root required — it reads system properties only.
#!/usr/bin/env bash
# check_cve_2026_0047.sh — Verify whether a connected Android device is
# vulnerable to CVE-2026-0047 (dumpBitmapsProto missing permission check).
# Requires: adb in PATH, one device/emulator connected.
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN
set -euo pipefail
# Check adb connectivity
if ! adb get-state 1>/dev/null 2>&1; then
echo "UNKNOWN — no adb device connected"
exit 2
fi
# Get Android version and patch level
SDK=$(adb shell getprop ro.build.version.sdk 2>/dev/null | tr -d '\r')
RELEASE=$(adb shell getprop ro.build.version.release 2>/dev/null | tr -d '\r')
PATCH_LEVEL=$(adb shell getprop ro.build.version.security_patch 2>/dev/null | tr -d '\r')
CODENAME=$(adb shell getprop ro.build.version.codename 2>/dev/null | tr -d '\r')
echo "Device info:"
echo " Android version : $RELEASE (SDK $SDK)"
echo " Security patch : $PATCH_LEVEL"
echo " Codename : $CODENAME"
echo ""
# CVE-2026-0047 only affects Android 16 QPR2 (Baklava)
# Android 16 QPR2 SDK level is expected to be 36 with codename Baklava
# Check if device is running a potentially affected build
# Not Android 16? Not affected.
if [[ "$RELEASE" != "16"* ]] && [[ "$CODENAME" != *"Baklava"* ]]; then
echo "PATCHED — device is not running Android 16 QPR2; CVE-2026-0047 does not apply."
exit 0
fi
# Check if this is a QPR2 build (look for QPR2 indicators in build fingerprint)
BUILD_FP=$(adb shell getprop ro.build.fingerprint 2>/dev/null | tr -d '\r')
if [[ "$BUILD_FP" != *"QPR2"* ]] && [[ "$BUILD_FP" != *"qpr2"* ]] && [[ "$CODENAME" != *"Baklava"* ]]; then
echo "PATCHED — device is Android 16 but not QPR2; CVE-2026-0047 does not apply."
exit 0
fi
# Device is Android 16 QPR2 — check patch level
if [[ -z "$PATCH_LEVEL" ]]; then
echo "UNKNOWN — could not determine security patch level."
exit 2
fi
# Compare patch level to fix date (2026-03-01)
FIX_DATE="2026-03-01"
if [[ "$PATCH_LEVEL" < "$FIX_DATE" ]]; then
echo "VULNERABLE — Android 16 QPR2 with security patch $PATCH_LEVEL (before $FIX_DATE)."
echo " Apply security patch level 2026-03-05 or later."
exit 1
else
echo "PATCHED — security patch level $PATCH_LEVEL is at or after $FIX_DATE."
exit 0
fi