FlawOpen

flawopen.com/Teardowns/cve-2026-49878-android-wpa-supplicant-oob-write

● CVE-2026-49878 · CVSS 7.2 · High
FlawOpen Security Research

CVE-2026-49878: Android Wi-Fi wpa_supplicant Heap Out-of-Bounds Write

Android’s October 2026 bulletin rates this Wi-Fi RCE flaw High. In wpa_supplicant, two int arrays were allocated by byte count; AOSP fixes both with os_calloc. The CVE record says System privileges are required.

💡 Plain English Explainer (ELI5)

A shelf holds a fixed number of boxes, but the clerk measures space in inches and allocates only one inch per box. The clerk then places full boxes into that space, overrunning the shelf. In CVE-2026-49878, wpa_supplicant treated a count of integers as a count of bytes, then wrote integer results into the undersized buffers. Google’s patch allocates the requested number of integers at their actual size.

Core Concepts & Subsystem Terms

wpa_supplicant
Android’s Wi-Fi supplicant component, which manages wireless authentication and related 802.11 interactions.
SCS response
A Stream Classification Service response action frame handled by the Robust AV code path. The affected handler processes it only when an SCS request is pending and its dialog token matches.
Out-of-bounds write (CWE-787)
A program writes beyond the memory region reserved for an object. Here the allocation used bytes while later code indexed the buffer as an array of int elements.
os_zalloc / os_calloc
wpa_supplicant allocation helpers. The vulnerable calls supplied only the element count as a byte size; the patch uses os_calloc(count, sizeof(int)) to reserve and zero the required array storage.
Android security patch level (SPL)
The date string Android uses to identify a device’s installed security update level. Google says 2026-10-01 or later addresses the issues in the October 2026 bulletin; device makers control rollout to their products.

Framework mappings

  • CWE reference for the weakness described in this guide: CWE-787

Root Cause Analysis

wpas_handle_robust_av_scs_recv_action allocates scs_resp[0] and scs_resp[1] as int * arrays. Before the fix, each call was os_zalloc(num_active_scs), which reserves num_active_scs bytes. The handler later stores integer IDs and status codes at indexed positions, so the required capacity is num_active_scs * sizeof(int) bytes. Existing checks require an ongoing request, a matching dialog token, a nonzero count that fits the remaining frame, and no more responses than active SCS entries; those checks do not correct the allocation-unit mismatch. The AOSP patch changes both allocations to os_calloc(num_active_scs, sizeof(int)). This exact defect and correction are documented in Google’s public commit; the article does not infer a controllable code-execution path from the out-of-bounds write.

Step-by-Step Attack Flow

Step 1

A response frame is dispatched

The Android Wi-Fi event handling path routes a Robust AV SCS Response action frame to the affected wpa_supplicant handler. The documented path is remote/network-facing, but the public sources do not establish that an arbitrary unauthenticated transmitter can satisfy every runtime precondition.

Step 2

Request state and response bounds are checked

The handler requires an outstanding SCS request and a matching dialog token, then checks response count against frame length and the active SCS list. NVD’s CISA-ADP vector is AV:N/AC:L/PR:H/UI:N; preserve its High privileges-required rating and do not re-label this as an unauthenticated zero-click flaw.

Step 3

Integer results exceed the byte allocation

The old code reserves one byte per active entry but stores int values. The bounds on the element count do not make the allocation large enough in bytes, creating the out-of-bounds write.

Step 4

The October patch corrects the allocation size

Google’s AOSP change allocates num_active_scs elements with element size sizeof(int) for both arrays. Do not infer a specific exploit payload or claim that the published diff demonstrates arbitrary code execution.

Source Code: Flaw vs. Secure Implementation

This is the source-level AOSP change in commit d131540379d631d7dcb09b0169e4462bc65abcca, not reconstructed pseudocode. os_zalloc(n) uses n as a byte size; os_calloc(count, size) reserves count elements of the requested size and zero-initializes them. The repair fixes both parallel response arrays and retains the existing allocation-failure cleanup.

UNPATCHED FLAW
/* AOSP pre-fix: num_active_scs is an element count,
 * but os_zalloc receives it as a byte count. */
scs_resp[0] = (int *) os_zalloc(num_active_scs);
if (!scs_resp[0])
    return;

scs_resp[1] = (int *) os_zalloc(num_active_scs);
if (!scs_resp[1]) {
    os_free(scs_resp[0]);
    return;
}
HARDENED SECURE PATCH
/* AOSP fix: allocate one full int for each entry. */
scs_resp[0] = os_calloc(num_active_scs, sizeof(int));
if (!scs_resp[0])
    return;

scs_resp[1] = os_calloc(num_active_scs, sizeof(int));
if (!scs_resp[1]) {
    os_free(scs_resp[0]);
    return;
}

Engineering & System Hardening Checklist

Sources