Your office baby-cam is whispering its GPS coordinates to anyone on the same Wi-Fi, but nobody outside the building can hear it
CVE-2026-13230 affects TP-Link Kasa EC70 v4 and EC71 v4 consumer smart cameras running firmware prior to 2.4.1 Build 20260621. The local discovery service on UDP port 9999 responds to unauthenticated get_sysinfo requests with a JSON payload containing precise sub-meter GPS coordinates, hardware identifiers (oemId, hwId, deviceId, MAC addresses), the user-assigned device alias, and the full firmware version string. The payload is "encrypted" with a trivial XOR cipher that Wireshark decodes natively. Any device on the same Layer 2 network can query the camera with a single UDP packet — no credentials, no session, no complexity.
The vendor scored this 5.3 (Medium) under CVSS 4.0, while the discovering researcher (Christopher Childress / BadChemical) argued for 7.1. For an enterprise managing 10,000 hosts, the vendor score is actually *generous*. These are consumer-grade IoT cameras unlikely to appear in production infrastructure at meaningful scale. The attack vector is adjacent-network only (AV:A), meaning the attacker must already be on the same LAN. The impact is pure information disclosure — no code execution, no integrity compromise, no availability impact. The leaked data (GPS coordinates, hardware IDs) is a privacy concern but does not enable lateral movement, privilege escalation, or data exfiltration from enterprise systems. This is backlog-tier work for most shops.
3 steps from start to impact.
Attacker gains Layer 2 adjacency
- Physical proximity or prior network compromise
- Layer 2 reachability to the camera's subnet
- Enterprise networks typically segment IoT devices onto dedicated VLANs
- Guest Wi-Fi is usually isolated from IoT segments
- Requires physical presence or prior foothold — this is a post-access step
Send unauthenticated UDP discovery packet
{"system":{"get_sysinfo":{}}} to port 9999 on the camera's IP address. No authentication token, session cookie, or API key is required. The packet can be crafted with the researcher's PoC tool KasaJSON.py or any UDP socket library. The XOR "encryption" is a known static cipher documented since 2016 (softScheck HS110 research).- Knowledge of camera IP address or ability to broadcast/scan the subnet
- UDP port 9999 reachable from attacker's position
- Firewall rules on IoT VLANs may block arbitrary UDP traffic between hosts
- Network monitoring may flag port scanning on IoT segments
get_sysinfo payloads on port 9999. Darktrace, Vectra, and similar NDR tools flag unusual IoT-to-IoT or workstation-to-IoT lateral communication.Decode response and extract GPS + device metadata
- Successful receipt of the UDP response
- The information gained is limited to physical location and device fingerprinting — it does not grant further system access
- GPS coordinates of a known office building are often already public information
The supporting signals.
| In-the-Wild Exploitation | No known exploitation in the wild. Not listed on CISA KEV. No threat actor campaigns documented. |
|---|---|
| Proof of Concept | Public. KasaJSON.py by Christopher Childress (BadChemical) on GitHub. Standalone Python script, trivial to execute. |
| EPSS Score | 0.00382 — bottom quartile. Extremely low predicted exploitation probability. |
| KEV Status | Not listed. No CISA KEV entry as of 2026-09-08. |
| CVSS Vector | Vendor CVSS 4.0: CVSS:4.0/AV:A/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N (5.3). User-provided CVSS 3.1: CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N (6.5). Key: Adjacent network attack vector, confidentiality-only impact. |
| Affected Versions | Kasa EC70 v4 and EC71 v4 running firmware prior to 2.4.0 Build 20260520. Vulnerable firmware documented: 2.3.26 Build 20240425. |
| Fixed Versions | Firmware 2.4.0 Build 20260520 rel.4191 or 2.4.1 Build 20260621 rel.76536 for both EC70 v4 and EC71 v4. |
| Scanning / Exposure Data | These are consumer-grade IoT cameras not indexed on Shodan or Censys in meaningful numbers for enterprise contexts. The vulnerable service (UDP 9999) is LAN-only and not internet-routable by design. |
| Disclosure Date | 2026-07-15. Researcher writeup published 2026-07-16. |
| Researcher | Christopher Childress (handle: BadChemical). Also discovered the companion CVE-2026-9770 (hardcoded RSA keys, CVSS 8.6). |
noisgate verdict.
The single most decisive factor is minimal enterprise deployment footprint — TP-Link Kasa EC70/EC71 are consumer-grade cameras almost never deployed in managed enterprise environments, and the adjacent-network-only attack vector further compounds the population narrowing to near-zero real exposure. The impact ceiling is information disclosure of GPS coordinates, which does not enable lateral movement, privilege escalation, or any follow-on compromise of enterprise systems.
Why this verdict
- Adjacent-network-only attack vector (AV:A): The attacker must already be on the same Layer 2 segment as the camera. In any enterprise with basic network segmentation, IoT devices sit on isolated VLANs unreachable from user workstations or the internet. This alone narrows the reachable attacker population dramatically.
- Consumer IoT with negligible enterprise footprint: Kasa EC70/EC71 are consumer smart home cameras sold through Amazon and retail channels. Enterprise physical security deployments use Axis, Verkada, Hanwha, Milestone — not TP-Link Kasa. Fewer than 0.1% of enterprises managing 10,000+ hosts have these in their asset inventory.
- Information disclosure only — no execution, no escalation: The leaked data is GPS coordinates and hardware IDs. While this is a privacy concern, it does not provide credentials, shell access, or any pivot into enterprise systems. The GPS coordinates of a known office building are typically already public via Google Maps.
- Role multiplier: Not applicable. Kasa cameras do not occupy any high-value enterprise role (not a DC, hypervisor, IdP, PAM, CI/CD, backup server, network edge appliance, or security agent). They are peripheral IoT devices. Even if compromised, the blast radius is limited to the individual device — no domain, fleet, or supply-chain impact. The high-value role floor does not apply.
Why not higher?
Upgrading to MEDIUM or higher would require either a broader attack vector (network/internet-routable), a higher-value target class (enterprise infrastructure), or a more impactful outcome (code execution, credential theft enabling lateral movement). None of these conditions are met. The companion CVE-2026-9770 (hardcoded RSA keys, credential exposure) is the more serious finding in this pair and warrants separate assessment — this CVE standing alone leaks only location metadata.
Why not lower?
Dropping to IGNORE would understate the risk for the small number of organizations that *do* have these cameras on their networks. The PoC is public and trivial, the attack is zero-click with no authentication, and the leaked GPS data could enable physical security reconnaissance (identifying facility locations, camera placements) that feeds into physical intrusion planning. For organizations with these devices, a firmware update is warranted — just not urgently.
What to do — in priority order.
- Isolate cameras on a dedicated IoT VLAN with no inter-host communication — Place all Kasa cameras on a VLAN where devices cannot communicate with each other or with user workstations. Block UDP port 9999 between hosts on the segment. This eliminates the adjacent-network attack path entirely. No SLA pressure — LOW verdict means treat as backlog hygiene.
- Apply firmware 2.4.1 during next maintenance window — Update EC70 v4 and EC71 v4 cameras to firmware 2.4.1 Build 20260621, which removes GPS data from the
get_sysinforesponse and disables unauthenticated port 9999 queries. Coordinate with facilities/physical security team. No mitigation SLA applies for LOW severity. - Inventory and consider replacing consumer cameras with enterprise-grade alternatives — If these cameras serve any physical security function, evaluate migration to enterprise surveillance platforms (Axis, Verkada, Milestone) that offer centralized management, encrypted communications, and proper authentication. This addresses the broader pattern — CVE-2026-9770 in the same product line is more severe.
- WAF / reverse proxy in front of cameras — the vulnerable service is UDP port 9999 using a proprietary protocol, not HTTP. Web application firewalls have no visibility into this traffic.
- Changing the camera's Wi-Fi password — the vulnerability requires Layer 2 adjacency, not the camera's credentials. Any authenticated user on the same network segment can exploit it regardless of camera password strength.
- Disabling UPnP on the router — the discovery protocol on port 9999 is TP-Link's proprietary Smart Home Protocol, not UPnP/SSDP. Disabling UPnP has no effect on this service.
Crowdsourced verification payload.
Run this script from any host on the same network segment as the target camera. Invoke with: python3 check_cve_2026_13230.py <camera_ip>. Requires no special privileges — just UDP socket access and Layer 2 adjacency to the camera.
#!/usr/bin/env python3
"""Check for CVE-2026-13230: TP-Link Kasa EC70/EC71 unauthenticated GPS disclosure.
Usage: python3 check_cve_2026_13230.py <camera_ip>
Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
"""
import sys
import socket
import json
import struct
def encrypt(plaintext):
key = 171
result = struct.pack('>I', len(plaintext))
for c in plaintext:
a = key ^ ord(c)
key = a
result += bytes([a])
return result
def decrypt(ciphertext):
key = 171
result = ""
for b in ciphertext:
a = key ^ b
key = b
result += chr(a)
return result
def main():
if len(sys.argv) != 2:
print("Usage: python3 check_cve_2026_13230.py <camera_ip>")
sys.exit(2)
target = sys.argv[1]
port = 9999
payload = '{"system":{"get_sysinfo":{}}}'
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
sock.connect((target, port))
sock.sendall(encrypt(payload))
response = b""
while True:
chunk = sock.recv(4096)
if not chunk:
break
response += chunk
sock.close()
if len(response) <= 4:
print("UNKNOWN - No meaningful response from device.")
sys.exit(2)
decrypted = decrypt(response[4:])
try:
data = json.loads(decrypted)
sysinfo = data.get("system", {}).get("get_sysinfo", {})
has_gps = False
for key in sysinfo:
if "latitude" in key.lower() or "longitude" in key.lower() or "gps" in key.lower():
has_gps = True
break
if has_gps:
print("VULNERABLE - Device responded with GPS/location data via unauthenticated query.")
print(" Firmware: " + sysinfo.get("sw_ver", "unknown"))
sys.exit(1)
else:
print("PATCHED - Device responded but no GPS/location fields present in sysinfo.")
print(" Firmware: " + sysinfo.get("sw_ver", "unknown"))
sys.exit(0)
except json.JSONDecodeError:
print("UNKNOWN - Response received but could not parse JSON.")
sys.exit(2)
except socket.timeout:
print("UNKNOWN - Connection timed out. Device may be patched (port 9999 no longer responds) or unreachable.")
sys.exit(2)
except ConnectionRefusedError:
print("PATCHED - Port 9999 refused connection. Firmware 2.4.1+ disables unauthenticated access.")
sys.exit(0)
except Exception as e:
print(f"UNKNOWN - Error: {e}")
sys.exit(2)
if __name__ == "__main__":
main()If you remember one thing.
Sources
- TP-Link Security Advisory (CVE-2026-9770 & CVE-2026-13230)
- BadChemical IoT Vulnerability Research — Kasa EC71 Full Writeup
- CyberSecurity News — TP-Link Cameras MitM Attacks
- GBHackers — TP-Link Kasa Camera Credential and Geolocation Flaws
- CyberPress — TP-Link Kasa Camera Credential and Location Exposure
- CVEmon — CVE-2026-13230 Overview
- OffSeq Threat Radar — CVE-2026-13230
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.