This is a sharp knife locked inside another locked drawer
CVE-2026-0031 is an Android kernel memory-corruption bug in arch/arm64/kvm/hyp/nvhe/mem_protect.c: an integer overflow can turn size math into an out-of-bounds write, creating a local elevation-of-privilege path. Public Android references place it in the pKVM subcomponent, with fixes shipped in the March 2, 2026 Android Security Bulletin and addressed by devices at security patch level 2026-03-05 or later; the bulletin maps affected AOSP branches to 14, 15, 16, 16-qpr2.
The raw technical impact is ugly, but the user-provided 8.4/HIGH label overstates defender urgency for most enterprises. This is not a network entry bug; it is a local, post-foothold kernel escape that also sits in a narrower pKVM path, so real-world reach is meaningfully smaller than 'all Android devices' and far smaller than the CVSS base score implies.
4 steps from start to impact.
Land code execution on the device
PR:N, but on Android AV:L still means the attacker must already be *on the box* before this CVE matters.- Affected Android device under attacker control long enough to run code locally
- A delivery path such as sideloading, managed app abuse, supply-chain compromise, or a separate browser/app RCE
- Managed Play-only fleets, app vetting, and mobile threat defense cut off a lot of initial footholds
- This prerequisite already implies a prior compromise stage
Reach the vulnerable pKVM memory-protection path
mem_protect.c hypervisor-facing logic, not in a generic remotely reachable service. An exploit has to drive execution into the vulnerable HVC/memory-protection path on a device whose kernel build actually includes the affected pKVM code.- ARM64 Android device with the affected pKVM/AVF path present
- Kernel branch matching the vulnerable pre-fix code
- A viable trigger path from local execution into the mem_protect handlers
- Not every enterprise Android handset meaningfully exposes or uses this pKVM path
- OEM kernel differences reduce one-size-fits-all exploit portability
Trigger the integer overflow and corrupt kernel memory
- Precise input shaping to the vulnerable mem_protect routines
- A target where the corrupted object can be turned into a useful primitive
- Kernel exploit reliability is harder in practice than CVSS suggests
- Modern memory mitigations, allocator behavior, and vendor changes can make the write non-deterministic
Convert corruption into privilege escalation
- Reliable post-corruption primitive
- Ability to survive kernel defenses long enough to gain higher privileges
- Exploit engineering cost is non-trivial and likely device-specific
- No public exploitation evidence or public PoC lowers confidence that this is currently turnkey
The supporting signals.
| In-the-wild status | No KEV entry and no reviewed Android source says this CVE is exploited in the wild. The March 2026 bulletin explicitly notes limited exploitation for CVE-2026-21385, not for CVE-2026-0031. |
|---|---|
| PoC availability | I found public patch commits and public CVE records, but no public GitHub or Exploit-DB exploit in the reviewed primary-source set as of 2026-05-29. |
| EPSS | 0.00007 from the prompt, which is effectively floor-level exploit-likelihood. Percentile was not present in the reviewed primary sources. |
| KEV status | Not listed in CISA's Known Exploited Vulnerabilities catalog as of 2026-05-29. |
| CVSS vector reality check | CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H means *easy once local code is already running*. It does not mean remotely easy. |
| Affected scope | Android places this in Kernel components / pKVM. Updated AOSP versions in the bulletin are 14, 15, 16, 16-qpr2. |
| Fixed state | Devices at Android security patch level 2026-03-05 or later should contain the fix. NVD references patch commits 98661431, aff2255d, and f3a4b4d4. |
| Scanning and exposure data | This is not internet-scannable. Shodan/Censys/FOFA/GreyNoise are the wrong lens because the bug is a local kernel/pKVM path; use MDM patch inventory and device-model mapping instead. |
| Disclosure / reporter | Publicly disclosed 2026-03-02. The reviewed records do not credit an external researcher; this appears published through Android's normal bulletin process. |
noisgate verdict.
The decisive factor is attacker position: this bug is only useful after the attacker already has local code execution on the Android device. The second major reducer is population narrowing: the vulnerable code is in the pKVM path, not a broadly exposed network-facing service, so the reachable fleet slice is materially smaller than the base CVSS suggests.
Why this verdict
- Start from 8.4, then subtract for attacker position —
AV:Lon Android means the attacker must already execute code on the handset. That is a major real-world friction point because it assumes a prior compromise stage. - Subtract again for exposure population — Android maps this to
pKVMmem_protect.c, not a universal remotely reachable component. That narrows the affected population to devices and kernels that actually ship and exercise the vulnerable virtualization path. - Subtract again for threat intel reality — no KEV listing, no public exploit found in the reviewed primary-source set, and the prompt's EPSS (
0.00007) is near the floor. There is no present evidence that this is the kind of bug attackers are broadly operationalizing today.
Why not higher?
If this were remotely reachable, KEV-listed, or accompanied by active exploit reporting, the score would jump fast. But none of those amplifiers are present here, and the local-on-device requirement compounds with the pKVM-specific scope to keep this out of the HIGH bucket.
Why not lower?
Do not dismiss it as hygiene-only. This is still a kernel out-of-bounds write with no user interaction and no extra privileges once code is already running locally, so it can be the privilege-escalation stage that turns a contained app compromise into full device compromise.
What to do — in priority order.
- Enforce managed-app-only installs — Cut off the most realistic prerequisite: local attacker code. On enterprise Android, lock devices to managed Google Play or an approved private catalog and block sideloading; for a MEDIUM verdict there is no mitigation SLA, so do this in your normal mobile-hardening cycle while patching inside the remediation window.
- Quarantine out-of-date Android builds with MDM — Use compliance policy to flag devices below security patch level 2026-03-05 and restrict sensitive access until they update. There is no mitigation SLA for a MEDIUM verdict, so this is a risk-reduction control rather than an emergency containment step.
- Require Play Protect and mobile threat defense telemetry — This does not fix the kernel bug, but it raises the cost of the initial foothold by catching malicious apps, sideload attempts, and suspicious behavior earlier in the chain. For MEDIUM, deploy as part of standard mobile baseline maintenance rather than an urgent hot response.
- Map AVF/pKVM-capable models — Because the vulnerable code sits in the pKVM path, you want a clean list of device models and OEM builds that actually carry that attack surface. Use that list to prioritize remediation inside the 365-day patch window instead of treating every Android device as equally exposed.
- Perimeter firewalls or WAFs do not help; this is not a network-reachable service vulnerability.
- MFA does not help; the exploit path is local kernel escalation after code execution on the device.
- Asset inventory alone does not reduce risk; knowing a device is vulnerable is not the same as blocking the prerequisite local foothold.
- Verified Boot does not stop a runtime local kernel exploit on an already booted device.
Crowdsourced verification payload.
Run this on the Android target device shell through adb shell, for example: adb push check_cve_2026_0031.sh /data/local/tmp/ && adb shell sh /data/local/tmp/check_cve_2026_0031.sh. It needs no root for the patch-level check, but root or a permissive shell improves pKVM detection from dmesg and kernel config.
#!/system/bin/sh
# check_cve_2026_0031.sh
# Best-effort verifier for CVE-2026-0031 on Android devices.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
PATCH_DATE="2026-03-05"
get_prop() {
/system/bin/getprop "$1" 2>/dev/null
}
SPL="$(get_prop ro.build.version.security_patch)"
SDK="$(get_prop ro.build.version.sdk)"
ABI="$(get_prop ro.product.cpu.abi)"
BUILD="$(get_prop ro.build.fingerprint)"
MODEL="$(get_prop ro.product.model)"
has_pkvm="0"
root_hint="0"
# Root hint
if id 2>/dev/null | grep -q "uid=0"; then
root_hint="1"
fi
# Best-effort pKVM indicators
if [ -r /proc/cmdline ] && grep -qi "pkvm\|protected" /proc/cmdline 2>/dev/null; then
has_pkvm="1"
fi
if dmesg 2>/dev/null | grep -qi "pkvm\|protected kvm\|hypervisor"; then
has_pkvm="1"
fi
if [ -r /proc/config.gz ]; then
if zcat /proc/config.gz 2>/dev/null | grep -Eq '^CONFIG_KVM=y|^CONFIG_PROTECTED_KVM=y|^CONFIG_KVM_ARM_HOST=y'; then
has_pkvm="1"
fi
fi
is_date() {
echo "$1" | grep -Eq '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'
}
printf 'Model: %s\n' "$MODEL"
printf 'Build: %s\n' "$BUILD"
printf 'SDK: %s\n' "$SDK"
printf 'ABI: %s\n' "$ABI"
printf 'Security patch level: %s\n' "$SPL"
printf 'pKVM indicators found: %s\n' "$has_pkvm"
printf 'Root shell: %s\n' "$root_hint"
# Non-arm64 devices are unlikely to match this pKVM path cleanly.
case "$ABI" in
arm64* ) : ;;
* )
echo "UNKNOWN - Non-arm64 ABI; this script cannot confidently map CVE-2026-0031 exposure here."
exit 2
;;
esac
# If the Android security patch level is current enough, call it patched.
if is_date "$SPL"; then
if [ "$SPL" \> "$PATCH_DATE" ] || [ "$SPL" = "$PATCH_DATE" ]; then
echo "PATCHED - Security patch level is $SPL (>= $PATCH_DATE)."
exit 0
fi
else
echo "UNKNOWN - Could not parse Android security patch level."
exit 2
fi
# Older SPL on affected Android generations: vulnerable if we also see pKVM signals.
case "$SDK" in
34|35|36 )
if [ "$has_pkvm" = "1" ]; then
echo "VULNERABLE - Pre-$PATCH_DATE security patch level on an Android build with pKVM indicators."
exit 1
else
echo "UNKNOWN - Pre-$PATCH_DATE patch level, but no pKVM signal was readable from this shell. Treat as candidate vulnerable until OEM/MDM confirms otherwise."
exit 2
fi
;;
* )
echo "UNKNOWN - Android SDK level not in the bulletin's updated AOSP version set (14/15/16 family)."
exit 2
;;
esac
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.