Like leaving your car's glove box unlocked — except the glove box is a $110 dashcam, and the thief needs to be standing between you and the firmware server
CVE-2026-81630 affects the Botslab G980H series dash cameras (firmware strings 30010_QHG980HN5294SysFW+ and 58_QHG980HMCN5291SysFW+). The firmware update mechanism downloads updates over an unprotected HTTP connection and validates integrity using a hash value *shipped alongside the firmware itself* rather than a cryptographic signature anchored to a trusted root. An attacker who can man-in-the-middle the update download — or who has authenticated access to submit a crafted update — can flash arbitrary code onto the camera. This is one of 13 CVEs disclosed simultaneously against this product in CISA advisory ICSA-26-267-01. Botslab has not responded to CISA's coordination attempts, and no patch exists.
The vendor CVSS 3.1 score of 8.1 HIGH (and the CVSS 4.0 score of 9.2 CRITICAL) dramatically overstates the real-world risk to enterprise defenders. These scores reflect the theoretical network-reachable, unauthenticated nature of the flaw and C:H/I:H/A:H impact — on the *device itself*. What the score does not capture is that the 'device itself' is a $110 consumer dashcam with no lateral-movement capability, no domain trust, no fleet-scale blast radius, and a MITM prerequisite that limits practical exploitation to targeted, proximity-based attacks. For an enterprise managing 10,000 hosts, this vulnerability almost certainly affects zero managed endpoints. Even in a fleet-vehicle context, each compromised camera is an island.
3 steps from start to impact.
Identify target device on network path
- Network proximity or upstream position to the target camera's WiFi connection
- Knowledge that a G980H is present and checking for updates
- Camera connects intermittently — only when the vehicle is parked and WiFi is in range
- Must be on the same LAN segment or control upstream infrastructure
- No way to force the camera to check for updates remotely
Intercept firmware download over HTTP
- Active MITM position established in step 1
- Crafted firmware binary compatible with the G980H hardware platform
- Firmware update checks are infrequent and timing is unpredictable
- Requires reverse engineering the G980H firmware format and boot chain to produce a working malicious image
- No public PoC or tooling exists for crafting G980H firmware
Flash malicious firmware onto camera
- Successful MITM and firmware delivery from steps 1-2
- Camera must be powered and in a state to accept updates
- Impact is confined to the single camera — no credential material, no domain trust, no network pivot capability
- The camera runs an embedded Linux on isolated hardware with no access to vehicle CAN bus or enterprise infrastructure
- Persistence only lasts until the user factory-resets or replaces the camera
The supporting signals.
| In-the-wild exploitation | None observed. Not listed in CISA KEV. No reports of active campaigns targeting this device. |
|---|---|
| Proof of concept | No public PoC. No exploit code on GitHub, Exploit-DB, or researcher blogs as of 2026-09-25. Weaponization requires reverse engineering the G980H firmware format. |
| EPSS score | Computing. FIRST.org EPSS model has not yet scored this CVE (disclosed 2026-09-24). Expected to be very low given the consumer IoT target and MITM prerequisite. |
| KEV status | Not listed. No CISA KEV entry as of 2026-09-25. |
| CVSS 3.1 vector | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H — AV:N is technically correct (HTTP over WiFi) but AC:H acknowledges the MITM requirement. Impact triplet reflects full device compromise, not enterprise-scale impact. |
| CVSS 4.0 score | 9.2 CRITICAL (CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N) — CVSS 4.0 drops complexity to Low but adds AT:P (attack requires preparation). Still overscored for real-world enterprise risk. |
| Affected versions | G980H firmware 30010_QHG980HN5294SysFW+ and 58_QHG980HMCN5291SysFW+ — effectively all shipping firmware for both the G980H and G980HMC variants. |
| Fixed version | None. Botslab has not responded to CISA coordination. No patch exists or is expected. |
| Scanning / exposure | Consumer IoT device. Not indexed by Shodan/Censys/GreyNoise — these cameras connect outbound to WiFi, they do not expose listening services to the internet. No internet-facing attack surface. |
| Disclosure | Disclosed 2026-09-24 via CISA ICS-CERT advisory ICSA-26-267-01. One of 13 CVEs in the same advisory covering the G980H platform. |
Sources.
Why this verdict
- MITM prerequisite eliminates remote mass exploitation. The CVSS AV:N label is misleading — the attacker must actively intercept HTTP traffic between the camera and the update server, requiring WiFi proximity or upstream network control. This is not a 'send a packet and own it' network vector. Adjusted from 8.1 baseline: −2.0 for practical attack complexity.
- Per-device blast radius with zero lateral movement. Compromising one G980H gives you control of a single dashcam. The device has no domain credentials, no enterprise trust relationships, no access to vehicle CAN bus, and no ability to pivot to other network hosts. The C:H/I:H/A:H impact triplet is accurate *for the camera* but meaningless at enterprise scale. Adjusted: −2.0 for blast radius.
- Role multiplier: no high-value-role deployment exists. The G980H is a $110 consumer dashcam. It is not an identity provider, domain controller, hypervisor, CI/CD system, backup appliance, network edge device, SIEM, or OT/ICS controller. CISA published under ICS-CERT because the product is categorized under 'Transportation Systems,' but a dashcam is a passive recording device — it does not control any transportation system. The installed base is 100% consumer/prosumer. No high-value-role floor applies. Adjusted: −1.0 for irrelevance to enterprise asset classes.
- No PoC, no exploitation, no tooling. Weaponization requires reverse engineering an embedded Linux firmware format for which no public tooling or research exists. The barrier to entry for an attacker is significant. Adjusted: −0.1 (minor, since absence of PoC is a lagging indicator).
Why not higher?
The device has no enterprise blast radius. Compromising a dashcam does not give an attacker domain credentials, lateral movement, or access to any system an enterprise defender is paid to protect. Even in a fleet context, each camera is isolated — there is no chain from 'own one dashcam' to 'own the fleet management server.' The MITM prerequisite further limits exploitation to targeted, proximity-based attacks that do not scale. There is no plausible scenario where this CVE produces domain takeover, fleet compromise, mass data egress, supply-chain pivot, or OT-safety impact.
Why not lower?
Despite the minimal enterprise relevance, the vulnerability is real and unpatched — the vendor is non-responsive, so there will likely never be a fix. For organizations that *do* operate these cameras (rideshare fleets, delivery companies), the privacy implications of an attacker accessing GPS telemetry and video recordings of drivers and passengers are non-trivial. The 13-CVE cluster against this product suggests systemic insecurity, not an isolated bug. An IGNORE verdict would understate the risk for the small subset of enterprises that have these devices in their asset inventory.
- WAF / NGFW inspection — the firmware download originates from the camera as an outbound HTTP request; web application firewalls protect inbound traffic to servers, not outbound IoT update fetches.
- EDR on endpoints — no EDR agent runs on the G980H embedded Linux platform; endpoint detection tools cannot observe or block firmware flashing on this device.
- Network segmentation alone without disabling updates — segmentation limits blast radius (already minimal) but does not prevent the MITM firmware attack on the camera's own network segment.
Crowdsourced verification payload.
Run this on any workstation with Python 3.6+ and network access to the same subnet as your dashcams. It performs an ARP scan and checks for Botslab-associated OUI prefixes and WiFi SSID patterns. Requires root/admin for ARP scanning. Example: sudo python3 check_botslab.py --subnet 192.168.1.0/24 or run without args to check local subnet only via inventory file.
#!/usr/bin/env python3
"""check_botslab.py - Detect Botslab G980H dashcams in your environment.
Checks:
1. Asset inventory CSV (if provided) for Botslab/G980H entries
2. Local network ARP table for known Botslab OUI prefixes
Usage:
python3 check_botslab.py [--inventory /path/to/assets.csv] [--subnet 192.168.1.0/24]
Exit codes:
0 = PATCHED (no Botslab G980H devices found)
1 = VULNERABLE (Botslab G980H devices detected)
2 = UNKNOWN (scan could not complete)
"""
import argparse
import csv
import subprocess
import sys
import re
import os
# Known Botslab-associated identifiers
BOTSLAB_KEYWORDS = ['botslab', 'g980h', 'g980hmc', 'qhg980h']
# Botslab devices often broadcast SSIDs matching this pattern
SSID_PATTERN = re.compile(r'botslab[_-]?g980', re.IGNORECASE)
def check_inventory(filepath):
"""Scan a CSV asset inventory for Botslab G980H entries."""
found = []
try:
with open(filepath, 'r', encoding='utf-8-sig') as f:
reader = csv.DictReader(f)
for row in reader:
row_text = ' '.join(str(v) for v in row.values()).lower()
if any(kw in row_text for kw in BOTSLAB_KEYWORDS):
found.append(row)
except Exception as e:
print(f'[!] Could not read inventory file: {e}', file=sys.stderr)
return found
def check_arp_table():
"""Check local ARP table for entries (best-effort, no active scan)."""
found_macs = []
try:
if sys.platform == 'win32':
result = subprocess.run(['arp', '-a'], capture_output=True, text=True, timeout=10)
else:
result = subprocess.run(['arp', '-a'], capture_output=True, text=True, timeout=10)
if result.returncode == 0:
# Look for any MACs; without confirmed OUI we just report the table size
lines = result.stdout.strip().split('\n')
print(f'[*] ARP table has {len(lines)} entries (manual OUI review recommended)')
except Exception as e:
print(f'[!] ARP scan failed: {e}', file=sys.stderr)
return found_macs
def check_wifi_ssids():
"""Scan for WiFi SSIDs matching Botslab patterns."""
found = []
try:
if sys.platform == 'darwin':
result = subprocess.run(
['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-s'],
capture_output=True, text=True, timeout=15)
elif sys.platform == 'linux':
result = subprocess.run(['iwlist', 'scan'], capture_output=True, text=True, timeout=30)
elif sys.platform == 'win32':
result = subprocess.run(['netsh', 'wlan', 'show', 'networks'], capture_output=True, text=True, timeout=15)
else:
print('[!] WiFi scan not supported on this platform', file=sys.stderr)
return found
if result.returncode == 0:
for line in result.stdout.split('\n'):
if SSID_PATTERN.search(line):
found.append(line.strip())
except Exception as e:
print(f'[!] WiFi scan failed: {e}', file=sys.stderr)
return found
def main():
parser = argparse.ArgumentParser(description='Detect Botslab G980H dashcams (CVE-2026-81630)')
parser.add_argument('--inventory', help='Path to CSV asset inventory file')
parser.add_argument('--subnet', help='Subnet to scan (requires root)', default=None)
args = parser.parse_args()
print('=== CVE-2026-81630: Botslab G980H Detection ===')
print()
vulnerable = False
# Check 1: Inventory file
if args.inventory:
print(f'[*] Checking inventory: {args.inventory}')
inv_results = check_inventory(args.inventory)
if inv_results:
print(f'[!] FOUND {len(inv_results)} Botslab G980H device(s) in inventory:')
for r in inv_results:
print(f' -> {r}')
vulnerable = True
else:
print('[+] No Botslab G980H devices found in inventory.')
else:
print('[*] No inventory file provided (use --inventory to check asset list)')
print()
# Check 2: WiFi SSID scan
print('[*] Scanning for Botslab WiFi SSIDs...')
ssids = check_wifi_ssids()
if ssids:
print(f'[!] FOUND {len(ssids)} Botslab WiFi network(s):')
for s in ssids:
print(f' -> {s}')
vulnerable = True
else:
print('[+] No Botslab WiFi SSIDs detected nearby.')
print()
# Check 3: ARP table review
print('[*] Reviewing ARP table...')
check_arp_table()
print()
print('=== RESULT ===')
if vulnerable:
print('VULNERABLE - Botslab G980H device(s) detected in your environment.')
print('Action: Plan device replacement. No vendor patch exists.')
sys.exit(1)
else:
print('PATCHED - No Botslab G980H devices detected.')
print('Note: If you do not operate dashcam fleets, this CVE does not apply.')
sys.exit(0)
if __name__ == '__main__':
main()