Device Lab - Vector Source Mapping
Runbook 08 - Vector source mapping: components, versioning, repos, reach
Purpose: for each attack channel, this runbook names (1) the components that actually carry the channel, (2) exactly where each component's version lives on a real device so a CVE lookup can be grounded, (3) the open-source repository to clone and scan for security best-practice violations, and (4) how to estimate reach: how many active Android devices are exposed to a vulnerable component on average.
Companion to runbook 07 (CVE research). Channel names match specs/vector-keywords.json. All reach figures are estimates; the math is spelled out in section 6 so any number can be re-derived.
1. The device under test (anchor for every channel)
Lab reference device, Moto G04 class (MediaTek silicon):
| property | value | read on device via |
|---|---|---|
| chipset SoC | MT6769 (2x Cortex-A76 + 6x Cortex-A55, LTE Cat-7 modem on-die) | getprop ro.board.platform |
| Wi-Fi/BT/FM/GNSS combo | MT6631 (4-in-1 RF front-end, BT 4.1+HS, 802.11 a/b/g/n/ac single stream) | confirm via Settings > About, dumpsys bluetooth_manager |
| Android | 14 | getprop ro.build.version.release |
| security patch | 2025-03-05 (device build baseline) | getprop ro.build.version.security_patch |
Vendor datasheets disagree on some MT6769 numbers; always confirm on-device via labs/phone-redlab/scripts/collect-specs.sh and treat the local specs/*-build.json as the source of truth, not the marketing page.
Fleet assumption used everywhere below: active Android devices ~3.9 billion (StatCounter derived, mid-2026 estimates run 3.5-4.2B).
2. The fleet version baseline (shared by every channel)
Android OS-version distribution, Play-console snapshot window ending 2025-11-24 (developer.android.com/about/dashboards):
| Android | fleet share | that share x 3.9B devices |
|---|---|---|
| 16 | 7.5% | ~0.29B |
| 15 | 19.3% | ~0.75B |
| 14 | 17.2% | ~0.67B |
| 13 | 13.9% | ~0.54B |
| 12 | 11.4% | ~0.44B |
| 11 | 13.7% | ~0.53B |
| 10 | 7.8% | ~0.30B |
| 9 | 4.5% | ~0.18B |
| 8.x | 3.1% | ~0.12B |
| 7.x | 0.8% | ~0.03B |
| 6 and below | 0.7% | ~0.03B |
OS-layer fix cadence (how fast a patch reaches the fleet):
- Android Security Bulletin rows arrive on monthly patch rollouts; a device
is only covered after it actually receives that patch level.
- Play System Updates (Project Core / Mainline modules) deliver OS components
like the Bluetooth stack and WebView independent of the vendor OTA.
- Chipset/baseband fixes (MediaTek) ship only via vendor OTA for that exact
build tree - slowest channel, gated by patchLevel and baseband version.
So for reach math the defensible floor is the OS-version share; the ceiling depends on update cadence per component (section 3..7).
3. call_telephony - RIL, baseband, IMS, SIM
Components and where their versions live:
| component | what it is | version on device |
|---|---|---|
| Telephony framework | call/signal state, STK, cell broadcast | bundled with Android version (ro.build.version.release) |
| RIL/Radio | modem <-> framework abstraction | getprop gsm.ril.fulluicctype, gsm.ril.oeminfo; Android patch level does not cover vendor RIL |
| Baseband firmware | LTE modem firmware inside MT6769 | getprop gsm.version.baseband (MediaTek exposes a modem build string, e.g. MOLY.*) |
| IMS / VoLTE / VoWiFi | packet-domain call control | bundled with Android version + carrier config |
| SIM toolkit app | STK proactive commands | bundled; driven by the UICC |
Lookups to run: NVD filter cpe:2.3:o:google:android:<version> + keywords ril, radio, telephony, baseband, ims, volte, vowifi, stk, simtoolkit; the MediaTek security advisory (mediatek.com PSIRT, alias MTKPSIRT) for MT6769 modem rows; upstream bulletin fix dates decide likely_fixed vs maybe_open (runbook 07 section 4).
OSS repos to scan (clone each, run semgrep), and what to look for:
| repo (AOSP) | security patterns to scan |
|---|---|
| frameworks/opt/telephony | parse of SMS/PDU in InboundSmsHandler, carrier IMS config, C-style bounds on byte[] decode |
| packages/services/Telephony | IMS call forwarding, telephony app intents, exported components |
| hardware/ril (libril, reference-ril) | string handling on AT responses, missing bounds checks on unsolicited responses |
| hardware/interfaces/radio | HIDL/AIDL boundary: trust assumptions on vendor data crossing to framework |
Reach: the baseband + telephony stack is present in effectively every cellular Android phone - a floor of roughly the whole ~3.9B fleet on the OS-layer rows, and the full MT6769-gen modem population for silicon rows (gearing for how many phones shipped that modem; MediaTek ships on the order of a billion+ modem-bearing chips per year, of which MT6769-gen budget tier is a large slice). Note VoLTE/VoWiFi/IMS only exist on active 4G/5G lines of the same fleet; pure 2G/3G fallback lines lose the IMS leg.
Bugs to expect in repo scan: integer/buffer handling on queued PDUs, exported Telephony components without permission checks, trust in RIL responses.
4. sms_mms - parsers, WAP push, MMS
Components and versions:
| component | what it is | version on device |
|---|---|---|
| SmsMessage / GsmSmsCbMessage | SMS + cell-broadcast PDU parsing | bundled with Android version |
| MMS service + mmslib | MMS transport, MIME, attachment assembly | bundled; app-level MMS client varies (AOSP Messaging vs provider app) |
| WAP push / OTA settings | binary SMS/OTASP, carrier auto-config | bundled with Android version |
Lookups: NVD + keywords sms, mms, wap push, cell broadcast, pdu, stk; historic pattern: SMS/MMS parsers are a classic memory-corruption row (the Stagefright family) - any PDU-parsing CVE here is worthiness class B/A candidate.
OSS repos to scan and patterns:
| repo (AOSP) | patterns |
|---|---|
| frameworks/opt/telephony (cdma/gsm subpackages) | PDU decode bounds, concatenation length handling, enc=16-bit/7-bit decode |
| packages/apps/Messaging (AOSP client) | sending MMS with user-supplied content, Intent recipients, exported activities |
| packages/services/Mms | mmslib attachment handling, HTTP transport of MMS, ContentResolver URIs |
Reach: SMS parsing is reachable on every device with an active SIM - the whole ~3.9B fleet on the OS-layer rows; MMS parsing reach only on devices using an MMS-capable app (the wide default, so still multi-billion-scale). sms_mms had zero keyword hits in the reference run; keep the channel monitored - a baseband MMS row outranks most OS rows when it appears.
5. bluetooth - Fluoride stack (Mainline module)
Components and versions:
| component | what it is | version on device |
|---|---|---|
| Fluoride BT stack | full dual-mode stack, Mainline APEX com.google.android.bt (Android 13+); below 13, system/bt legacy | APEX module version via adb shell pm list packages for com.google.android.bt; stack reports version in adb shell dumpsys bluetooth_manager |
| BT framework + HAL | android.bluetooth API, HIDL transport | bundled with Android version |
| Vendor BT driver/fw | MT6631 RF + companion chip modem, kernel driver + firmware | kernel driver ver. via lsmod/dmesg (wmt/bluetooth lines); not an OS-patchable row - vendor OTA only |
Lookups: NVD + keywords bluetooth, l2cap, smp, gatt, hfp, avrcp, bdr/edr, ble, mt66; the MTK advisory for MT6631 rows. ASB Bluetooth component rows are OS-layer and patch-gated.
OSS repos to scan and patterns:
| repo (AOSP) | patterns |
|---|---|
| packages/modules/Bluetooth (Fluoride; legacy system/bt is its history) | C++ memory management on L2CAP/SMP/GATT paths, use-after-free in profile handlers, bounds on ATT length fields, fuzz targets present? (add harnesses: afl++/libFuzzer per protocol) |
| packages/modules/Bluetooth/android/app | exported BT app components, BluetoothSocket fd handling |
| frameworks/base (Bluetooth binder surface) | binder permission checks (only BLUETOOTH_PRIVILEGED callers may scan/pair) |
Reach: Bluetooth radio is present on essentially the whole fleet (~3.9B), and the Fluoride stack is the same code on every Android 13+ device; the APEX is updatable (Play System Update), so the current-stack population is the Android 13+ share (~58%) plus updatable-lower. Classic BR/EDR matters: most budget-tier phones still expose it, so RCE in BR/EDR paths reaches the widest set; BLE-only rows reach BLE-capable devices (Android 4.3+, virtually all).
Expected repo-scan findings: C++ UAF/double-free, integer wrap in packet length math, missing caller-address checks on HFP/AVRCP connections.
6. wifi_hotspot - WLAN stack, supplicant, hostapd, SoftAP
Components and versions:
| component | what it is | version on device |
|---|---|---|
| Wi-Fi framework | Wi-Fi service + Hotspot/P2P state machine; Mainline com.android.wifi (Android 13+), legacy frameworks/opt/net/wifi below | APEX version for the module; else Android version |
| wpa_supplicant | STA credential/EAP handling, P2P | wpa_cli -v prints the version; often vendor-patched |
| hostapd | AP/softAP, wpa2/3, 802.11k/r/v (MT6631-compatible) | hostapd -v; vendor-patched builds carry vendor strings |
| vendor WLAN driver + firmware | MT6631 RF + companion chip | dmesg wlan load lines, /sys/module/wlan*/version; vendor OTA gated |
Lookups: NVD + wifi, wpa, wpa2, wpa3, supplicant, hostapd, softap, hotspot, p2p, eap, mbo; FragAttacks-family rows (some on MTK wlan), Kr00k-class (e.g. CVE-2019-15126) hit MTK chipsets specifically.
OSS repos to scan and patterns:
| repo (AOSP) | patterns |
|---|---|
| external/wpa_supplicant_8 | EAP/message parsing (e wifi), IEs, key-reinstallation handling, length checks on RSN IE, ASN.1 in certificate paths |
| external/hostapd | hostap-side of the same: key derivation, roaming IE parsing, PMK lifetime handling |
| packages/modules/Wifi (module) + frameworks/opt/net/wifi (legacy) | hotspot/saved-network state management, permission checks on Wi-Fi APIs |
| hardware/interfaces/wifi | HAL boundary trust, vendor capabilities parsing |
Reach: Wi-Fi stack present on the whole fleet (~3.9B); softAP/hotspot present on the wide majority of smartphones, missing only on a thin number of US-carrier slab phones unless explicitly enabled. Wi-Fi rows are patch-gated exactly like the adjacent OS rows (ASB wifi component).
Expected repo-scan findings: missing bounds/validation on IEs and Action frames, no timeout on EAP state, insecure default PMK timeout.
7. email_delivery - the browser/WebView leg (the phishing opener)
This is the channel the human interacts with: a link lands via email/SMS and a WebView or browser opens it. The "browser" component IS the attack surface, more than the email client itself.
Components and versions:
| component | what it is | version on device | |
|---|---|---|---|
| Android System WebView | Chromium engine as a package (com.google.android.webview); Android 10+ ships Trichrome (WebView + Chrome installed as linked builds) | adb shell dumpsys webviewupdate (provider + versionName), or `pm list packages -f | grep webview`; NOT carried by Android version - it is a Play-updated component, ~6-week cadence |
| Chrome / provider browser | the in-app + default browser renderers | versionName via `pm list packages -f | grep com.android.chrome` |
| Email clients | Gmail/Outlook (proprietary) or AOSP packages/apps/Email (legacy) | app versionCode | |
| MIME/PDF/viewer chain | attachment handling before a link is clicked | app-level |
Critical security model: on Android 9 and lower the WebView cannot be updated (new WebView releases require Android 10+), so the ~5% of the fleet below Android 10 (~0.2B) keeps whatever WebView the factory shipped - a permanently stale browser unless the vendor backported. On Android 10+ (~95% of the fleet, ~3.7B) WebView updates arrive via Play largely within days-to-weeks; the vulnerable fraction is the update drift.
Lookups: NVD + chromium/webview/chrome/v8/blink briefly; WebView CVEs are in the ASB "Framework"/"Chromium" components with the fixed WebView version named - if the device's WebView is below that version the row is open even when patchLevel looks fine. This divergence (WebView version vs OS patch level) is the single most common reach mistake: always read dumpsys webviewupdate, never assume WebView follows the patch level.
OSS repos to scan (this is Chromium-scale; scan the Android-facing layer and your own integrations rather than all of Blink):
| repo | patterns |
|---|---|
| chromium src android_webview + content (mirror via chromium.googlesource.com) | insecure WebView configuration in any app that opens untrusted links: setJavaScriptEnabled on untrusted content, addJavascriptInterface exposure, setAllowFileAccess, trusting user-supplied URLs in Intent-based navigation |
| AOSP external/chromium-webview | prebuilt only - not current; do not treat as a trust anchor; confirm real WebView via dumpsys |
| Your app/client WebViews (Ask Avi codebase) | same config review + no webview debug on prod builds |
Reach: the browser/WebView is the widest single target in the model - ~100% of active Android devices have at least one renderer, and the phishing leg only needs the human to click. Average exposed population for a given WebView CVE roughly = (share of devices on WebView versions below the fix) x 3.9B; because WebView updates fast, per-version exposure in the Android 10+ fleet is a short-lived window, while the <Android 10 rump (~0.2B) stays exposed indefinitely - a permanently exploitable laggard population.
8. local_app (only counts with a remote leg)
Not a standalone channel: this lab cannot ship a malicious app to a real device, so local_app rows only count where a remote channel also matches (runbook 07 section 2).
| component | version on device | role |
|---|---|---|
| Org-installed apps (Ask Avi client etc.) | app versionCode | local apps are the first thing an attacker escalates into IF a remote leg lands |
| Android framework sandbox | Android version + patch level | the boundary privilege escalation crosses |
OSS repos to scan: your own client app code (manifest exported components, dangerous permission usage, WebView config - see section 7), and the Android framework app-level permission model in frameworks/base when deciding what a compromised app can reach.
Reach: quantified only through a remote leg - see the channel that landed.
9. Putting it together: reach math per CVE
reach_estimate(CVE) = active_devices (3.9B)
x OS-version share hosting the vulnerable component
x unpatched fraction for that component's update path
x silicon share for chipset-specific rows (MT6769 modem, MT6631 WLAN/BT)
Update-path multipliers to use:
| component | update path | unpatched fraction assumption |
|---|---|---|
| OS/Android rows | ASB patch rollout | ~share of devices not yet on the fix patch level (drift; 10-40%) |
| Bluetooth stack (13+) | Play System Update | low drift on current Android (10-25%) |
| WebView (Android 10+) | Play direct | very low drift on current versions (5-20%); the <Android 10 rump stays ~100% |
| Baseband / MTK silicon | vendor OTA only | highest drift (30-70%); decide per build tree and regionTier |
Example (phishing opener): a WebView row fixed in Chromium version N. Floor: Android 10+ fleet (~3.7B) is exposed until Play pushes the fix (days); laggard exposure: <Android 10 (~0.2B) stays exposed. So say "on the order of 3.5B+ transiently, half a billion-severity permanently." A baseband row on the other hand is "MT6769-gen phones on builds below the fix" - vendor field, often 100M-500M class, but reachable over the air.
Keep every estimate as a range with the math visible; update the fleet baseline (section 2) when the Play snapshot moves.
10. Recording and hygiene
- Write the per-CVE row with: component path, version read source (exact
getprop/dumpsys command), repo scanned, reach estimate, update-path class.
- The dashboard (/labs) and its run stats must never carry device
identifiers, baseband strings, or patch levels tied to an org device - public pages get only the sanitized summary.
- Scan repos, clone them read-only into the lab, never commit third-party
sources or results that name a real device.