Your robot vacuum trusts any certificate like a toddler trusts any stranger in a costume
CVE-2026-93291 is an improper certificate validation flaw (CWE-295) in the Eufy Omni C20 and Omni X10 Pro consumer robot vacuums running firmware prior to version 1.6.4. The device fails to validate TLS certificates when communicating with its cloud backend. An attacker who achieves man-in-the-middle positioning on the same network segment can present a self-signed or otherwise invalid certificate, intercept and modify traffic in transit, and ultimately inject payloads that achieve arbitrary code execution on the device. The flaw was reported by Jared of Somerset Recon and disclosed via CISA ICS advisory ICSA-26-267-02 on September 24, 2026. It is part of a trio of bugs (alongside CVE-2026-93289 for command injection and CVE-2026-93290 for hardcoded credentials) affecting the same product line.
The vendor CVSS of 9.4 CRITICAL is detached from enterprise reality. The score is mechanically derived from AV:N/AC:L/PR:N/UI:N, which implies a trivially exploitable internet-facing service — but the actual attack requires man-in-the-middle positioning on the local network where a *consumer robot vacuum* operates. That is not AC:L in any honest reading; it presupposes local network access via ARP spoofing, DNS poisoning, or a rogue access point. More fundamentally, the affected component is a home appliance. It is not an identity provider, a domain controller, a hypervisor, a backup server, or any other high-value enterprise asset. For a security team managing 10,000 hosts, the probability that a Eufy Omni C20 appears in their CMDB is near zero, and if it does, the blast radius of compromising it is confined to a single IoT device on (hopefully) a segmented VLAN. The 9.4 CRITICAL label will waste triage cycles if left uncontested.
4 steps from start to impact.
Attain local network access
- Physical proximity to target Wi-Fi network or prior compromise of a host on the same LAN
- Knowledge of Wi-Fi PSK or ability to deploy a rogue AP
- Enterprise networks with 802.1X / WPA3 block rogue devices
- IoT devices should be on segmented VLANs unreachable from attacker workstations
- Most enterprises do not operate consumer robot vacuums on production networks
Establish man-in-the-middle position
bettercap or mitmproxy are standard for this. The attacker must sustain the MitM for the duration of the exploit, which requires ongoing network presence.- Active Layer 2 access on the vacuum's VLAN
- No dynamic ARP inspection (DAI) or DHCP snooping enabled on the switch
- Managed switches with DAI and DHCP snooping defeat ARP-based MitM
- DNS-based MitM is blocked by DNS-over-HTTPS or internal DNS security policies
- The vacuum may not generate frequent cloud traffic, limiting interception windows
Present fraudulent TLS certificate
- Sustained MitM position from Step 2
- Vacuum initiates outbound TLS connection during the interception window
- The vacuum must be actively communicating — not idle or powered off
- Certificate pinning on the cloud-side does not help here since the *client* is the one failing validation
Inject malicious payload for code execution
- Full TLS MitM from Step 3
- Knowledge of the vacuum's cloud protocol and payload format (not publicly documented)
- No public PoC or exploit code exists
- Requires reverse engineering of proprietary Eufy cloud protocol
- Payload must be crafted for the specific embedded ARM/MIPS firmware
The supporting signals.
| In-the-wild exploitation | None reported. CISA states no known public exploitation as of disclosure. Not observed in any threat campaign. |
|---|---|
| Proof-of-concept | No public PoC. Somerset Recon (Jared) reported the flaw through coordinated disclosure to CISA. No exploit code, write-up, or reproduction steps have been published. |
| EPSS score | Not yet scored. CVE was reserved 2026-09-17 and published 2026-09-24 — EPSS typically lags 7–14 days. Expected to be very low (<0.01) given IoT niche and no PoC. |
| KEV status | Not listed. No CISA Known Exploited Vulnerabilities catalog entry as of 2026-09-25. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L — 9.4. The AV:N and AC:L are misleading: practical exploitation requires MitM positioning on the local network, which is closer to AV:A/AC:H in reality. |
| Affected versions | Eufy Omni C20 and Omni X10 Pro, all firmware versions < 1.6.4. |
| Fixed version | Firmware 1.6.4 — delivered via Eufy app OTA update. |
| Scanning / exposure | Not applicable. The Eufy Omni C20 is a consumer robot vacuum. It does not expose listening ports to the internet. Shodan/Censys/GreyNoise have zero relevant results — the device is a Wi-Fi client, not a server. |
| Disclosure date | 2026-09-24 via CISA ICS advisory ICSA-26-267-02. CVE reserved 2026-09-17. |
| Reporting researcher | Jared of Somerset Recon, reported to CISA via coordinated disclosure. Also reported CVE-2026-93289 (command injection) and CVE-2026-93290 (hardcoded credentials) in the same product. |
Sources.
Why this verdict
- MitM prerequisite is not AC:L. The CVSS vector claims AV:N/AC:L, but exploitation requires the attacker to achieve man-in-the-middle positioning on the device's local Wi-Fi segment. This demands either physical proximity, a compromised host on the same VLAN, or a rogue AP — each of which implies prior access. In enterprises with 802.1X, WPA3, DAI, and IoT segmentation, this is AC:H at best and often infeasible. Adjustment: −2.0 from baseline.
- Consumer IoT device with near-zero enterprise footprint. The Eufy Omni C20 is a $250 robot vacuum sold at Walmart. It does not appear in enterprise CMDBs, is not managed by endpoint management tools, and is not part of any business-critical workflow. The probability of encountering one on a 10,000-host enterprise network is negligible. Even in smart-office scenarios, it would be a single unmanaged IoT device. Adjustment: −3.0 from baseline.
- No PoC, no exploitation, no tooling. There is no public exploit code, no documented reproduction path, and no known campaign targeting this vulnerability. The attacker would need to reverse-engineer Eufy's proprietary cloud protocol to weaponize the MitM into code execution. This is not a one-click exploit. Adjustment: −1.0 from baseline.
- Role multiplier: no high-value role applies. The Eufy Omni C20 is a consumer appliance. It cannot serve as an identity provider, domain controller, hypervisor, backup server, PKI/CA, CI/CD runner, database tier, EDR agent, network edge appliance, SIEM, or OT/SCADA controller. 100% of its installed base occupies the lowest-value role possible — a home cleaning appliance. The blast radius of compromise is a single IoT device: no domain takeover, no fleet compromise, no supply-chain pivot, no data exfiltration of regulated data. The high-value role floor does NOT apply. Compromise yields: access to home floor-mapping data and a potential (but limited) network pivot point on a consumer Wi-Fi segment.
- CISA ICS classification is a red herring. CISA ICS-CERT publishes advisories for all embedded/IoT devices under its charter, including consumer products. The ICS label does not mean this device is deployed in industrial control environments. No evidence of Eufy robot vacuums in OT/ICS/SCADA environments exists.
Why not higher?
The vulnerability is technically real and the cert validation failure is a legitimate CWE-295 flaw. If an attacker achieves MitM on the same network and can reverse-engineer the cloud protocol, code execution is plausible. However, every step in the chain requires conditions that are either extremely unlikely in enterprise environments (the device being present at all) or blocked by standard network security controls (802.1X, VLAN segmentation, DAI). The blast radius — a single robot vacuum — does not justify anything above LOW.
Why not lower?
IGNORE would be defensible for most enterprises, but if your organization has deployed IoT vacuums on corporate Wi-Fi (smart offices, executive suites, coworking spaces), the MitM → RCE chain is real and the compromised device could serve as a minimal network foothold. The CISA advisory also creates a compliance checkbox that some frameworks require tracking. LOW rather than IGNORE accounts for the non-zero possibility of presence and the regulatory paper trail.
- Network-level TLS inspection / SSL proxy — the vacuum uses its own TLS stack to connect to Eufy cloud services; enterprise SSL inspection proxies would need to MitM the vacuum themselves, which ironically is the same attack the CVE describes. The proxy cannot force the vacuum to validate a different certificate chain.
- EDR / endpoint protection — the Eufy Omni C20 is an embedded Linux device. No enterprise EDR agent runs on it. Host-based detection is not possible.
- Vulnerability scanning (Nessus, Qualys, Rapid7) — standard enterprise vulnerability scanners do not have plugins for consumer robot vacuum firmware versions. These devices will not appear in scan results.
Crowdsourced verification payload.
Run this script from any workstation on the same network as the Eufy vacuum. It attempts to identify Eufy devices via mDNS/UPnP and check their advertised firmware version. Requires Python 3.6+ and no special privileges. Example: python3 check_eufy_cve_2026_93291.py --subnet 192.168.1.0/24
#!/usr/bin/env python3
"""CVE-2026-93291 checker — Eufy Omni C20 / X10 Pro firmware version audit.
Scans local subnet for Eufy devices and checks firmware against fixed version 1.6.4.
Usage: python3 check_eufy_cve_2026_93291.py --subnet 192.168.1.0/24
Exit codes: 0=PATCHED/no devices, 1=VULNERABLE, 2=UNKNOWN
"""
import argparse
import ipaddress
import socket
import sys
import struct
import json
import re
FIXED_VERSION = (1, 6, 4)
TIMEOUT = 2
SSDP_ADDR = "239.255.255.250"
SSDP_PORT = 1900
def parse_version(ver_str):
parts = re.findall(r'(\d+)', ver_str)
if len(parts) >= 3:
return tuple(int(p) for p in parts[:3])
return None
def ssdp_discover(subnet):
"""Send SSDP M-SEARCH and look for Eufy devices."""
msg = (
'M-SEARCH * HTTP/1.1\r\n'
'HOST: 239.255.255.250:1900\r\n'
'MAN: "ssdp:discover"\r\n'
'MX: 2\r\n'
'ST: ssdp:all\r\n'
'\r\n'
)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.settimeout(TIMEOUT + 1)
sock.sendto(msg.encode(), (SSDP_ADDR, SSDP_PORT))
devices = []
try:
while True:
data, addr = sock.recvfrom(4096)
response = data.decode('utf-8', errors='ignore').lower()
if 'eufy' in response or 'anker' in response or 'omni' in response:
devices.append({'ip': addr[0], 'response': data.decode('utf-8', errors='ignore')})
except socket.timeout:
pass
sock.close()
return devices
def check_device(device):
"""Parse SSDP response for firmware version info."""
resp = device.get('response', '')
ver_match = re.search(r'(?:firmware|fw|version)[:/\s]*(\d+\.\d+\.\d+)', resp, re.IGNORECASE)
if ver_match:
ver = parse_version(ver_match.group(1))
if ver:
return ver
return None
def main():
parser = argparse.ArgumentParser(description='CVE-2026-93291 Eufy Omni C20 checker')
parser.add_argument('--subnet', default='192.168.1.0/24', help='Subnet to scan (default: 192.168.1.0/24)')
args = parser.parse_args()
print(f"[*] Scanning for Eufy devices via SSDP on {args.subnet}...")
devices = ssdp_discover(args.subnet)
if not devices:
print("[*] No Eufy/Anker IoT devices found on this network segment.")
print("[*] If you know Eufy Omni C20/X10 Pro devices are present, check firmware")
print(" version manually in the Eufy Clean app: Settings > Device Info > Firmware.")
print(" Fixed version: >= 1.6.4")
print("")
print("UNKNOWN — no Eufy devices detected via SSDP; verify manually.")
sys.exit(2)
vulnerable = False
unknown = False
for dev in devices:
ip = dev['ip']
ver = check_device(dev)
if ver is None:
print(f"[?] Eufy device at {ip} — firmware version not parseable from SSDP.")
print(f" Check manually in Eufy Clean app. Fixed version: >= 1.6.4")
unknown = True
elif ver < FIXED_VERSION:
print(f"[!] VULNERABLE — Eufy device at {ip} running firmware {'.'.join(map(str, ver))} (< 1.6.4)")
vulnerable = True
else:
print(f"[+] PATCHED — Eufy device at {ip} running firmware {'.'.join(map(str, ver))} (>= 1.6.4)")
print("")
if vulnerable:
print("VULNERABLE — one or more Eufy devices need firmware update to >= 1.6.4.")
sys.exit(1)
elif unknown:
print("UNKNOWN — could not determine firmware version for all devices.")
sys.exit(2)
else:
print("PATCHED — all detected Eufy devices are on firmware >= 1.6.4.")
sys.exit(0)
if __name__ == '__main__':
main()