This is a hidden trapdoor inside a locked room, not an unlocked front door
CVE-2026-0037 is an Android kernel-side memory corruption bug in arch/arm64/kvm/hyp/nvhe/ffa.c, mapped in the March 2, 2026 Android bulletin to the Protected Kernel-Based Virtual Machine subcomponent. The vendor description says exploitation is local, needs no extra privileges, and needs no user interaction once the attacker already has code execution on the device; the March 2026 bulletin says devices at security patch level 2026-03-05 or later contain the fix.
The raw impact is ugly because kernel or hypervisor-adjacent memory corruption can end in full device compromise. But the vendor's 8.4 baseline overstates enterprise urgency for most fleets: this is not remotely reachable, it usually needs a prior foothold such as a malicious app or physical/ADB access, and the vulnerable code sits in a narrower pKVM/FFA path rather than a universal network-facing service. That keeps it in HIGH, but below panic level.
4 steps from start to impact.
Land code execution on the device
adb install, or a separate browser/message/client exploit chain. This CVE is not an initial-access bug; it is a privilege-escalation stage used after code is already executing in user space.- Attacker can execute code on the Android device
- Target is an affected Android build that has not received the March 2026 patch level
- Modern MDM, Play Protect, allow-listing, and app-store restrictions cut off the easiest entry paths
- No network-reachable attack surface for this CVE by itself
Trigger the ffa.c logic flaw with a custom LPE harness
ffa.c logic error in the pKVM/FFA code path referenced by Google's fix commit. The likely weaponized tool here is a purpose-built native exploit binary, not an off-the-shelf internet worm, because exploitation depends on kernel internals and device build specifics.- Target device uses the vulnerable pKVM/Protected KVM code path
- Attacker can run native code locally
- Kernel hardening and OEM differences do not break the exploit
- The affected subcomponent is narrower than a generic Android framework bug
- Device, kernel, and OEM fragmentation make reliable exploitation harder than the CVSS vector suggests
- I found no authoritative public PoC or exploit kit reference
Escape the app sandbox into kernel/system control
- Exploit succeeds on the exact device/kernel build
- Post-exploitation protections do not immediately reboot or quarantine the device
- Verified Boot, SELinux, hardware-backed attestation, and strong MDM posture can limit useful persistence even after temporary elevation
- Blast radius is one device at a time, not a server-side tenant-wide event
Use the rooted device as a data and identity pivot
- Corporate data is present on the device
- Attacker maintains meaningful control after privilege escalation
- Mobile threat defense, conditional access, and attestation failures can sever enterprise access quickly
- This does not directly translate into mass remote exploitation across 10,000 devices
2026-03-05. Conditional access and mail/VPN gating reduce the value of a compromised handset and should be applied within 30 days.- A WAF does nothing here because there is no web request to filter; this is a local kernel bug.
- Perimeter IDS/IPS is weak value because exploitation does not require network reachability to the vulnerable component.
- Generic server-side internet exposure scanning will not find this; your inventory and patch-compliance data matter more than Shodan counts.
The supporting signals.
| In-the-wild status | No public exploitation evidence found in AOSP, NVD, or CISA KEV. The March 2, 2026 Android bulletin flags a different CVE as exploited, not this one. |
|---|---|
| KEV status | Not listed in the CISA KEV catalog as checked now. |
| Proof-of-concept availability | No authoritative public PoC located. NVD and AOSP reference the patch and bulletin; I found no upstream exploit write-up or Exploit-DB/GitHub reference tied to this CVE. |
| EPSS | 0.00003 per the user-supplied intel, which is effectively floor-level risk. Third-party mirrors also place it around 0.00%–0.01%, reinforcing that this is not showing the usual exploitation-likelihood signals. |
| CVSS vector readout | CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H means local-only, no privileges, no user interaction, but high impact if won. In practice, AV:L is the giant brake pedal here. |
| Affected component | AOSP maps CVE-2026-0037 to Kernel → Protected Kernel-Based Virtual Machine and the fixing commit touches arch/arm64/kvm/hyp/nvhe/ffa.c. |
| Affected versions | Google says devices patched to security patch level 2026-03-05 or later address the issue. Treat Android builds before that level as suspect unless your OEM documents a backport. |
| Fixed version / patch train | Fixed via the March 2026 Android Security Bulletin; operationally, the safe state is Android security patch level 2026-03-05 or later or an OEM-equivalent backport. |
| Exposure / scanning reality | This is a local kernel LPE, so Shodan/Censys/FOFA style internet exposure counts are basically not applicable. There is no remotely exposed socket to count; your real exposure metric is unpatched managed Android devices. |
| Disclosure / reporter | Disclosed 2026-03-02. The Android fix commit credits Arve Hjønnevåg as reporter. |
Sources.
Why this verdict
- Baseline accepted, then trimmed: vendor score
8.4/HIGHis reasonable for worst-case impact, but I cut it becauseAV:Lmeans this is not initial access and not remotely wormable. - Requires prior foothold: the first prerequisite implies the attacker already landed code on the device through some other channel; that is compounding downward pressure in real enterprise environments.
- Reachable population is narrower than 'all Android': AOSP ties this to Protected Kernel-Based Virtual Machine /
ffa.c, not a broad user-space service every handset exposes equally. - Modern controls should block step 1 more often than step 2: app allow-listing, Play Protect, MDM restrictions, and ADB controls remove a lot of practical paths into the vulnerable state.
- No exploitation telemetry amplifier: no KEV listing, no bulletin note of active abuse, and floor-level EPSS keep this out of the top patch queue.
Why not higher?
Because this is not a remote edge bug and not a one-click fleet event. It needs a prior local foothold and then a device/build-specific exploit path, which sharply narrows who can actually use it at scale.
Why not lower?
Because once exploited, this is still a kernel-side privilege escalation on a managed endpoint, and that can expose mail, tokens, work-profile data, and device trust. For enterprises with meaningful Android fleet usage, that is too much downstream blast radius to call merely backlog hygiene.
Crowdsourced verification payload.
Run this on an auditor workstation with adb installed and USB/network debugging access to the Android target. Invoke it as ./check-cve-2026-0037.sh <device-serial> or ./check-cve-2026-0037.sh for the default attached device; no root is required, but you need permission to use adb shell on the device.
#!/usr/bin/env bash
# check-cve-2026-0037.sh
# Determine likely exposure to CVE-2026-0037 using Android patch level and basic device facts.
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=tool/usage error
set -u
TARGET_SERIAL="${1:-}"
ADB_BIN="${ADB_BIN:-adb}"
REQUIRED_SPL="2026-03-05"
fail() {
echo "UNKNOWN - $1"
exit 2
}
need_cmd() {
command -v "$1" >/dev/null 2>&1 || { echo "UNKNOWN - missing required command: $1"; exit 3; }
}
adb_cmd() {
if [ -n "$TARGET_SERIAL" ]; then
"$ADB_BIN" -s "$TARGET_SERIAL" "$@"
else
"$ADB_BIN" "$@"
fi
}
need_cmd "$ADB_BIN"
STATE="$(adb_cmd get-state 2>/dev/null || true)"
[ "$STATE" = "device" ] || fail "adb device not available (state: ${STATE:-none})"
getprop_safe() {
local key="$1"
local value
value="$(adb_cmd shell getprop "$key" 2>/dev/null | tr -d '\r')"
echo "$value"
}
SPL="$(getprop_safe ro.build.version.security_patch)"
ANDROID_RELEASE="$(getprop_safe ro.build.version.release)"
SDK="$(getprop_safe ro.build.version.sdk)"
MODEL="$(getprop_safe ro.product.model)"
FINGERPRINT="$(getprop_safe ro.build.fingerprint)"
ARCH="$(getprop_safe ro.product.cpu.abi)"
if [ -z "$SPL" ]; then
fail "could not read ro.build.version.security_patch"
fi
normalize_date() {
local d="$1"
if [[ "$d" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "$d"
else
echo ""
fi
}
SPL_N="$(normalize_date "$SPL")"
REQ_N="$(normalize_date "$REQUIRED_SPL")"
if [ -z "$SPL_N" ] || [ -z "$REQ_N" ]; then
fail "unparseable patch level (device='$SPL', required='$REQUIRED_SPL')"
fi
echo "Device: ${MODEL:-unknown}"
echo "Android: ${ANDROID_RELEASE:-unknown} (SDK ${SDK:-unknown})"
echo "ABI: ${ARCH:-unknown}"
echo "Patch level: $SPL_N"
echo "Fingerprint: ${FINGERPRINT:-unknown}"
# Lexicographic compare is safe for YYYY-MM-DD format.
if [[ "$SPL_N" < "$REQ_N" ]]; then
echo "VULNERABLE - security patch level is older than $REQUIRED_SPL"
exit 1
fi
if [[ "$SPL_N" == "$REQ_N" || "$SPL_N" > "$REQ_N" ]]; then
echo "PATCHED - security patch level is $SPL_N (>= $REQUIRED_SPL)"
exit 0
fi
fail "unable to determine status"