← Back to Feed CACHED · 2026-09-26 22:22:14 · CACHE_KEY CVE-2026-0047
CVE-2026-0047 · CWE-280 · Disclosed 2026-03-02

Android ActivityManagerService dumpBitmapsProto Missing Permission Check

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

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.

"Bitmap-stealing bug scoped to Android 16 QPR2; local-only, patched 7 months ago, zero wild exploitation."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Craft a zero-permission APK

The attacker builds an Android app that declares no permissions in its manifest. The app contains code to open a raw Binder connection to the 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.
Conditions required:
  • Android development environment
  • Knowledge of Binder transaction code #117
Where this breaks in practice:
  • Any competent mobile security researcher can do this, but turning it into a campaign requires a delivery mechanism
Detection/coverage: Google Play Protect static analysis should flag raw IBinder.transact() calls targeting system service transaction codes.
STEP 02

Deliver APK to target device

The attacker must get the APK installed on a victim's Android 16 QPR2 device. Distribution options: sideloading via phishing link, embedding in a trojanized app on a third-party store, or attempting to sneak past Google Play review. Enterprise MDM policies that block unknown sources or enforce app whitelisting stop this step entirely.
Conditions required:
  • Victim device running Android 16 QPR2 with patch level < 2026-03-01
  • App installation succeeds (sideloading enabled or Play Store evasion)
Where this breaks in practice:
  • Google Play Protect on-device scanning
  • Enterprise MDM sideloading restrictions
  • Play Store automated review pipeline
  • Very small target population (QPR2-only)
Detection/coverage: MDM compliance policies flag devices with sideloading enabled; Play Protect logs installation of unknown apps.
STEP 03

Invoke dumpBitmapsProto via Binder

On launch, the app obtains the 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.
Conditions required:
  • App is running on a vulnerable Android 16 QPR2 build
  • ActivityManagerService is reachable (always true on a booted device)
Where this breaks in practice:
  • 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
Detection/coverage: Runtime detection would require Binder-level auditing or SELinux custom policy; no standard EDR/MTD agent hooks this today.
STEP 04

Extract and exfiltrate bitmaps

ActivityManagerService writes a protobuf stream containing PNG-encoded bitmaps from all foreground and recent-task windows to the pipe file descriptor. The app reads the pipe, scans for PNG magic bytes (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.
Conditions required:
  • Other apps are actively rendering UI (foreground or recent tasks)
  • Network access for exfiltration (or physical retrieval)
Where this breaks in practice:
  • 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
Detection/coverage: Network DLP or MTD agents may flag unusual HTTPS POST volumes from an unknown app. On-device, no standard detection exists.
03 · Compensating Control

1
MEDIUM 5.0→IGNORE 0.0
SEVERITY REDUCED
Enforce minimum security patch level via MDM compliance policy — Configure your MDM (Intune, Workspace ONE, JAMF, etc.) to require security patch level ≥ 2026-03-05 for Android 16 QPR2 devices. Non-compliant devices should be quarantined from corporate resources. No mitigation SLA applies at MEDIUM — go straight to the 365-day remediation window, but given this patch has been available since March 2026, compliance enforcement should be immediate.
2
MEDIUM 5.0→LOW 2.5
SEVERITY REDUCED
Block sideloading and unknown sources via MDM policy — Ensure the 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.
3
MEDIUM 5.0→LOW 3.0
SEVERITY REDUCED
Verify Google Play Protect is enabled and not overridden — Play Protect's on-device scanning should detect and block APKs that invoke raw Binder transactions against system services. Ensure MDM policy enforces Play Protect and prevents users from disabling it. This adds a probabilistic detection layer but is not guaranteed against novel evasion.
4
MEDIUM 5.0→MEDIUM 5.0
Audit fleet for unpatched Android 16 QPR2 devices — Query your MDM for devices reporting 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.
What doesn't work
  • 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 ActivityManagerService is a system-level service accessible from both personal and work profiles. Work profile isolation does not prevent a personal-side app from invoking dumpBitmapsProto(), and the dump may include bitmaps from work-profile apps in recent tasks.
04 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone 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-conceptPublic PoC available. mobilehackinglab/CVE-2026-0047-poc on GitHub — fully functional, extracts 63 PNGs from a Baklava emulator. Educational reproduction by Mobile Hacking Lab.
EPSS0.00138 (0.14%) — 3rd percentile. Exploit Prediction Scoring System rates this as extremely unlikely to be exploited in the next 30 days.
KEV statusNot listed. No CISA Known Exploited Vulnerabilities entry as of 2026-09-27.
CVSS vectorCVSS: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 versionsAndroid 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 versionSecurity patch level 2026-03-05 or later. Fix committed to AOSP; Pixel devices received OTA in March 2026. OEM rollout varies.
Scanning / exposureNot 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 date2026-03-02 — published in Android Security Bulletin ASB-A-465136263.
ResearcherDiscovered via Android security research; PoC independently reproduced by Mobile Hacking Lab with full patch-diff analysis and Binder transaction reverse engineering.

Sources.

  1. Android Security Bulletin — March 2026
  2. GitHub Advisory GHSA-x394-245g-p4p8
  3. Mobile Hacking Lab PoC
  4. SentinelOne Vulnerability Database
  5. NVD Detail
  6. CyberStrike CVE Detail
  7. HelpNetSecurity — Android March 2026 Patch
05 · The Call

Final Verdict
↓ DOWNGRADED to MEDIUM (5.0/10)

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.

06 · Verification

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.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/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