Vulnerability Assessment¶
Modules: 43 total (25 CVE checks + 11 non-CVE checks + meta-modules)
The vuln_scanner meta-module orchestrates all registered checks against a target and produces a unified assessment report. Each check probes for a specific vulnerability or posture weakness using non-invasive techniques --- the default mode never sends intrusive packets.
Vulnerability assessment is the bridge between Reconnaissance (knowing what the target exposes) and Exploitation (attacking confirmed vulnerabilities). Running vulnscan first tells you which exploits will succeed before you attempt them, saving time and avoiding unnecessary disruption to the target.
Detection Methods¶
Behavioral Detection¶
How it works: Sends crafted-but-legal packets to the target and observes how the response differs from what a patched implementation would produce. The key insight is that vulnerable and patched targets exhibit measurably different behavior --- different response sizes, different timing, different error codes, or different state transitions. Blue-Tap sends the same probe multiple times and applies statistical analysis (jitter analysis) to distinguish genuine vulnerability signals from network noise.
Behavioral detection is the most reliable method because it directly tests the target's code path. If the target responds with leaked memory bytes where a patched target would respond with zeros, the vulnerability is present regardless of what version the target claims to run.
Examples:
- MTU jitter analysis for CVE-2019-3459 --- vulnerable targets leak extra bytes in L2CAP responses
- Role swap acceptance for CVE-2017-0783 --- vulnerable targets accept BNEP role changes they should reject
Jitter Analysis
Many behavioral checks send the same probe 5--10 times and measure the variance in response size or timing. A patched target produces identical responses each time (zero jitter). A vulnerable target that leaks heap memory produces responses with varying content (non-zero jitter) because the heap contents differ between calls. This statistical approach reduces false positives significantly compared to single-probe detection.
Compliance Detection¶
How it works: Tests whether the target correctly implements mandatory requirements from the Bluetooth specification. The Bluetooth Core Specification defines "shall" requirements --- things every implementation must do. A target that violates a "shall" requirement has a bug. When that bug aligns with a known CVE's root cause, the target is likely vulnerable.
Compliance detection sends a deliberately invalid input and checks if the target rejects it (correct behavior) or processes it (vulnerable behavior). These checks are typically fast because they require only a single packet exchange.
Examples:
- PSM=0 rejection for CVE-2022-42896 --- the spec requires rejecting LE Credit Based connections with PSM 0
- EATT MTU validation for CVE-2023-35681 --- the spec requires minimum MTU enforcement
Compliance vs Behavioral
Compliance checks are binary (reject/accept) and fast. Behavioral checks require multiple probes and statistical analysis. Use --cve to run a single check when you know what you are looking for; run the full vulnscan to cast a wide net.
Status Taxonomy¶
Two Separate Fields
Blue-Tap uses two distinct status fields. Never conflate them.
execution_status (lifecycle)¶
How the check executed, regardless of what it found. This tells you whether the check ran properly.
| Status | Meaning |
|---|---|
completed |
Check ran to completion |
failed |
Check could not complete (target unreachable, protocol error) |
error |
Internal error in the check logic |
skipped |
Check was skipped (prerequisites not met) |
timeout |
Check timed out waiting for target response |
module_outcome (semantic)¶
What the check determined about the target. This is the finding you care about.
| Outcome | Meaning |
|---|---|
confirmed |
Target is vulnerable (high confidence) |
inconclusive |
Insufficient signal to determine vulnerability |
pairing_required |
Check needs pairing to proceed (and pairing was not available) |
not_applicable |
Check does not apply to this target (wrong protocol, wrong device type) |
not_detected |
Target appears not vulnerable |
Reading Results¶
Understanding vulnscan output is critical for prioritizing your assessment. Here is what each outcome means operationally:
confirmed¶
The check has high-confidence evidence that the target is vulnerable. The target exhibited behavior that only a vulnerable implementation would produce --- leaked memory, accepted invalid input, or responded in a way that is inconsistent with a patched stack.
Action: This vulnerability is real. Proceed to Exploitation if authorized, or document it as a confirmed finding.
inconclusive¶
The check could not reach a definitive conclusion. This happens when the target's response is ambiguous --- it does not clearly match either "vulnerable" or "patched" behavior. Common causes: the target is a different OS than expected, the response varies in a way the check does not model, or network conditions introduced noise.
Action: Review the evidence manually. Run the check again with -vv for debug output. Consider running an HCI capture during the check to inspect the raw packet exchange.
pairing_required¶
The check needs an authenticated connection (pairing) to proceed, and pairing was not available during the scan. Several checks --- particularly those targeting pairing-related CVEs like CVE-2019-2225 and CVE-2022-25837 --- require actually initiating a pairing procedure.
Action: Re-run the check with pairing enabled if your assessment scope allows it. If the target requires user interaction for pairing (e.g., PIN entry, numeric comparison), you will need physical access to the target device.
not_applicable¶
The check does not apply to this target. For example, a BLE-only check against a Classic-only device, or an AVRCP check against a device that does not support AVRCP.
Action: No action needed. This is expected behavior --- the check correctly determined it is irrelevant for this target.
not_detected¶
The target appears not vulnerable. The check ran successfully and the target's behavior is consistent with a patched implementation.
Action: No action needed, but note that not_detected is not the same as "proven safe." The check tests one specific attack vector; the target may have other issues, or the check may have a blind spot.
Error and Timeout
When execution_status is error or timeout, the module_outcome is unreliable. An error means the check itself had a problem (bug, unexpected state); a timeout means the target did not respond within the allowed window. In both cases, the target's vulnerability status is unknown. Re-run the check, possibly with a longer timeout or after verifying the target is reachable.
CVE Coverage¶
Full CVE Table (25 CVEs)¶
For detailed detection methods, packet-level analysis, and per-CVE usage examples, see the CVE Detection Matrix.
| CVE | Protocol | Detection | Pairing Required |
|---|---|---|---|
| CVE-2017-0785 | SDP / L2CAP | Behavioral: continuation replay | No |
| CVE-2017-0783 | BNEP | Behavioral: role swap acceptance | No |
| CVE-2017-13258/13260/13261/13262 | BNEP | Behavioral: extension header heap jitter (family of 4 related info leaks) | No |
| CVE-2018-9359/9360/9361 | L2CAP | Behavioral: SCID jitter on malformed CMD_CONN_REQ (family of 3 related OOB reads) | No |
| CVE-2018-9365 | BLE SMP | Compliance: SMP on BR/EDR CID | No |
| CVE-2019-2225 | Pairing | Behavioral: JustWorks silent pairing | Yes |
| CVE-2019-3459 | L2CAP | Behavioral: MTU jitter | No |
| CVE-2020-0022 | Raw ACL | Behavioral: BlueFrag boundary | No (DarkFirmware) |
| CVE-2020-0556 | HID | Behavioral: unbonded L2CAP | No |
| CVE-2020-12352 | L2CAP / A2MP | Behavioral: A2MP info_data jitter | No |
| CVE-2020-26558 | Pairing | Behavioral: LE SC public key echo | Yes |
| CVE-2021-0507 | AVRCP | Compliance: event_id=0x00 rejection | No |
| CVE-2022-0204 | GATT | Compliance: Prepare Write boundary | No |
| CVE-2022-20345 | BLE L2CAP | Compliance: eCred 6-CID overflow | No |
| CVE-2022-25837 | Pairing | Behavioral: SSP method confusion | Yes |
| CVE-2022-39176 | AVRCP | Behavioral: GET_CAPABILITIES jitter | No |
| CVE-2022-42895 | L2CAP | Behavioral: EFS option jitter | No |
| CVE-2022-42896 | BLE L2CAP | Compliance: LE PSM=0 rejection | No |
| CVE-2023-35681 | GATT | Compliance: EATT MTU validation | No |
| CVE-2023-45866 | HID | Behavioral: HOGP pre-auth write | No |
| CVE-2024-34722 | BLE SMP | Behavioral: legacy pairing wrong Confirm | No |
| CVE-2025-20700/01/02 | Airoha | Behavioral | No |
| CVE-2026-23395 | BLE L2CAP | Compliance: duplicate ECFC Identifier | No |
Non-CVE Checks (11)¶
Non-CVE checks assess the target's Bluetooth security posture --- configuration weaknesses that are not tied to a specific vulnerability but increase attack surface.
BLE Posture¶
| Check ID | What It Tests |
|---|---|
pairing_method |
Which pairing method the target accepts (JustWorks, Passkey, etc.) |
writable_gatt |
GATT characteristics that are writable without authentication |
eatt_support |
Enhanced ATT support and configuration |
pairing_method check
This check determines what the target accepts for BLE pairing. A device that accepts JustWorks pairing provides zero protection against MITM --- any device can pair without user confirmation. Passkey Entry and Numeric Comparison provide progressively stronger MITM protection. The check reports which methods the target supports.
RFCOMM Posture¶
| Check ID | What It Tests |
|---|---|
service_exposure |
Sensitive services exposed via RFCOMM |
hidden_rfcomm |
RFCOMM channels not advertised in SDP |
encryption_enforcement |
Whether encryption is required before data transfer |
authorization_model |
Authorization behavior for RFCOMM connections |
automotive_diagnostics |
Automotive diagnostic protocols accessible over RFCOMM |
automotive_diagnostics
This check is particularly relevant for IVI assessment. Some head units expose OBD-II or vendor-specific diagnostic protocols over RFCOMM, giving an attacker access to vehicle bus communication. A positive finding here means the Bluetooth interface can reach the vehicle's internal network.
General Posture¶
| Check ID | What It Tests |
|---|---|
pin_lockout |
Whether brute-force PIN attempts trigger lockout |
device_class |
Device class flags and implications |
lmp_features |
LMP feature page analysis for security-relevant capabilities |
lmp_features check
Analyzes the target's LMP feature pages for security-relevant capabilities: Secure Connections support, encryption pause/resume, LE Secure Connections, and other features that affect what attacks are viable. A device without Secure Connections is vulnerable to KNOB and BIAS; a device with encryption pause/resume may be vulnerable to encryption toggle attacks.
CLI Usage¶
Run all checks against a target¶
Target is optional
Omitting the target address triggers an interactive device picker --- Blue-Tap scans for nearby devices and lets you select one. Run blue-tap vulnscan with no arguments to try it.
Full vulnscan output
$ sudo blue-tap vulnscan 4C:4F:EE:17:3A:89
Session: blue-tap_20260416_150012
── Vulnerability Assessment (4C:4F:EE:17:3A:89) ───────────────────────────────
Running 36 applicable checks (25 CVE + 11 posture)...
[CVE-2017-0785] BlueBorne SDP Info Leak
status: completed | outcome: not_detected
[CVE-2017-0783] BlueBorne BNEP Panu Role
status: completed | outcome: not_detected
[CVE-2019-9506] KNOB Key Negotiation ← this is detected by fingerprint
status: completed | outcome: confirmed
evidence: Target accepted key_size=1 (min_key_length=1)
[CVE-2020-0022] BlueFrag ACL Boundary
status: completed | outcome: confirmed
evidence: Response length jitter detected (delta=8..24 bytes)
[CVE-2020-12352] BadKarma A2MP Info Leak
status: completed | outcome: confirmed
evidence: A2MP info_data size variance 0..16 bytes across 10 probes
[CVE-2023-45866] HOGP Pre-Auth HID Injection
status: completed | outcome: confirmed
evidence: Write to Report characteristic accepted without authentication
[pairing_method] BLE Pairing Method
status: completed | outcome: observed
finding: Target accepts JustWorks (no MITM protection)
[encryption_enforcement] RFCOMM Encryption
status: completed | outcome: observed
finding: Data transfer accepted before encryption on channels 12, 15
── Summary ─────────────────────────────────────────────────────────────────────
Confirmed vulnerabilities: 4
Inconclusive: 2
Pairing required: 3
Not applicable: 8
Not detected: 15
Run a single CVE check¶
--cve accepts two formats:
- A CVE identifier such as
CVE-2020-0022→ runsassessment.cve_2020_0022. - A non-CVE posture check short name → runs
assessment.<short_name>. Valid short names:service_exposure,hidden_rfcomm,encryption_enforcement,writable_gatt,eatt_support,pairing_method,pin_lockout,device_class,lmp_features,authorization_model,automotive_diagnostics.
# Posture-only check (no CVE)
blue-tap vulnscan 4C:4F:EE:17:3A:89 --cve writable_gatt
blue-tap vulnscan 4C:4F:EE:17:3A:89 --cve service_exposure
Target optional
blue-tap vulnscan (no TARGET) launches the interactive device picker. Tab-completion of --cve values is not offered by Click; paste the short name directly.
BlueBorne detection
The CVE-2017-1000251 / BlueBorne check only fingerprints the target's BlueZ version from its SDP response. Earlier versions also read the local host's bluetoothd --version, which mis-attributed the scanner's version string to the remote target. If the target's SDP does not advertise a BlueZ version the check reports inconclusive rather than guessing.
Example output
$ sudo blue-tap vulnscan 4C:4F:EE:17:3A:89 --cve CVE-2020-0022
14:35:02 ● Running: BlueFrag Boundary Probe
14:35:02 ● Starting assessment.cve_2020_0022
14:35:02 ● Opened raw HCI socket on hci1
14:35:02 ✔ DarkFirmware confirmed on hci1 (Hook 1 backup = 91d81080)
14:35:03 ● Connecting ACL to 4C:4F:EE:17:3A:89...
14:35:04 ● ACL connected (handle=0x000B)
14:35:04 ● Sending fragmented Echo: pkt1=L2CAP hdr only, pkt2=95 bytes (1 short)
14:35:04 ● Probing 5 times for response jitter...
14:35:06 ✔ Response length jitter detected (delta=8..24 bytes across 5 probes)
14:35:06 ✔ Completed assessment.cve_2020_0022
╭─ Vulnerability Finding ──────────────────────────────────────────────────╮
│ ■ CRITICAL confirmed CVE-2020-0022 (BlueFrag) CVE-2020-0022 │
│ │
│ Evidence: Response length jitter 8-24 bytes indicates heap data leak │
│ Confidence: high │
│ Affected: Android 8.0 - 9.0 │
╰──────────────────────────────────────────────────────────────────────────╯
Enable active (intrusive) checks¶
Example output
$ sudo blue-tap vulnscan 4C:4F:EE:17:3A:89 --active --yes
14:40:00 ● Running: Vulnerability Scanner
14:40:00 ● Scanning 4C:4F:EE:17:3A:89 for vulnerabilities and attack-surface indicators...
14:40:00 ● Active mode enabled — intrusive checks included
──────────── Check 1: Secure Simple Pairing ────────────────
14:40:01 ✔ SSP supported (IO capability: DisplayYesNo)
──────────── Check 3: Reachability ─────────────────────────
14:40:02 ✔ L2CAP ping succeeded (latency=12ms)
──────────── Check 5: Non-CVE RFCOMM Checks ────────────────
14:40:08 ● Non-CVE check started: service_exposure
14:40:08 ✔ Non-CVE check finished: service_exposure -> observed
14:40:08 ● Non-CVE check started: hidden_rfcomm
14:40:12 ✔ Non-CVE check finished: hidden_rfcomm -> observed
──────────── Check 8: L2CAP CVE Probes ─────────────────────
14:40:15 ● CVE check started: CVE-2019-3459
14:40:17 ✔ CVE check finished: CVE-2019-3459 -> not_detected
14:40:17 ● CVE check started: CVE-2020-0022
14:40:19 ✔ CVE check finished: CVE-2020-0022 -> confirmed
──────────── Check 12: Active BIAS Probe ───────────────────
14:40:25 ● CVE check started: CVE-2020-10135 (active)
14:40:28 ● Spoofing 11:22:33:44:55:66 via DarkFirmware RAM patch
14:40:30 ✔ CVE check finished: CVE-2020-10135 -> confirmed
╭─ Vulnerability Findings (12 found) ─────────────────────────────────────╮
│ Severity Status Name CVE │
│ ■ CRITICAL confirmed BlueFrag Boundary CVE-2020- │
│ 0022 │
│ ■ HIGH confirmed BIAS Impersonation CVE-2020- │
│ 10135 │
│ ■ MEDIUM observed Hidden RFCOMM channels N/A │
│ (3 undisclosed) │
│ ■ MEDIUM observed Encryption not enforced N/A │
│ (ch 12, 15) │
│ ■ INFO inconclusive CVE-2017-0785 CVE-2017- │
│ 0785 │
│ ... 7 more (not_detected / not_applicable) │
╰──────────────────────────────────────────────────────────────────────────╯
Vulnerability Scan Summary
──────────────────────────────────────────────────
Target 4C:4F:EE:17:3A:89
Total Findings 12
Confirmed 2
Inconclusive 1
Pairing Required 2
Not Applicable 5
Critical/High 2
Provide a phone address for relay-based attacks¶
Example output
$ sudo blue-tap vulnscan 4C:4F:EE:17:3A:89 --phone 11:22:33:44:55:66
14:45:00 ● Running: Vulnerability Scanner
14:45:00 ● Phone address 11:22:33:44:55:66 will be used for impersonation checks
14:45:00 ● Scanning 4C:4F:EE:17:3A:89 for vulnerabilities...
──────────── Check 12: BIAS Impersonation ──────────────────
14:45:30 ● CVE check started: CVE-2020-10135
14:45:30 ● Spoofing phone 11:22:33:44:55:66 → probing target acceptance
14:45:32 ⚠ CVE check finished: CVE-2020-10135 -> unverified
14:45:32 ● Tip: Use --active to enable active BIAS validation
╭─ Vulnerability Findings (9 found) ──────────────────────────────────────╮
│ Severity Status Name CVE │
│ ■ INFO unverified BIAS Requires Active CVE-2020- │
│ Validation 10135 │
│ ■ MEDIUM inconclusive CVE-2017-0785 CVE-2017- │
│ 0785 │
│ ... 7 more (not_detected / not_applicable / pairing_required) │
╰──────────────────────────────────────────────────────────────────────────╯
Phone Address
Some checks (particularly BIAS and impersonation-related CVEs) need a "phone" address --- the address of a device that is legitimately paired with the target. The check will probe whether the target can be fooled into accepting a connection from a spoofed address. In an IVI assessment, this is typically the owner's phone address, obtained from SDP/PBAP reconnaissance.
Fleet scanning (multiple targets by device class)¶
Example output
$ sudo blue-tap fleet --duration 10 --class ivi
14:50:00 ● Fleet scan: discovering devices (10s, filter=ivi)
14:50:10 ✔ Found 3 device(s), 2 match class filter 'ivi'
┌──────────────────────┬──────────────────┬────────────┬───────┐
│ Address │ Name │ Class │ RSSI │
├──────────────────────┼──────────────────┼────────────┼───────┤
│ 4C:4F:EE:17:3A:89 │ MY-CAR-AUDIO │ Car Audio │ -45 │
│ D0:03:4B:52:8C:11 │ IVI-SYSTEM │ Car Audio │ -58 │
└──────────────────────┴──────────────────┴────────────┴───────┘
14:50:11 ● Assessing 4C:4F:EE:17:3A:89 (MY-CAR-AUDIO)...
14:52:30 ✔ Completed: 2 confirmed, 1 inconclusive
14:52:31 ● Assessing D0:03:4B:52:8C:11 (IVI-SYSTEM)...
14:54:15 ✔ Completed: 0 confirmed, 3 inconclusive
Fleet Summary
──────────────────────────────────────────────────
Devices scanned 2
Total findings 6
Confirmed vulns 2 (4C:4F:EE:17:3A:89)
Highest severity CRITICAL
Interpreting Results¶
A typical vulnscan produces a list of check results. Focus on:
module_outcome: confirmed--- target is vulnerable with high confidence. See Reading Results above for operational guidance.module_outcome: inconclusive--- review the evidence manually; the check could not reach a definitive conclusionmodule_outcome: pairing_required--- re-run with pairing available if this check matters to your assessmentexecution_status: errorortimeout--- the check itself had problems; results are unreliable
Prioritizing Findings
Focus on confirmed outcomes first. For an IVI target, the highest-impact findings are typically:
- KNOB/BIAS/BLUFFS --- allow MitM and impersonation of paired phones
- CVE-2023-45866 --- allows HID injection without pairing
- CVE-2020-0022 --- remote code execution (BlueFrag)
- encryption_enforcement failure --- allows traffic interception
- automotive_diagnostics exposure --- allows vehicle bus access
What's Next?¶
With confirmed vulnerabilities identified, you can proceed to exploitation:
- Exploitation --- attack confirmed vulnerabilities, understand the full attack chain
- Discovery --- if you need to find more targets
- Reconnaissance --- if you need more information about the target before deciding what to exploit
- CLI Reference --- full command reference