Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-13491

CVE-2026-13491: xiaozhi-esp32 MQTT DoS Vulnerability

CVE-2026-13491 is a denial of service vulnerability in xiaozhi-esp32 MQTT Goodbye Handler that allows remote attackers to disrupt service availability. This post explains its technical details, affected versions, and mitigation.

Published:

CVE-2026-13491 Overview

CVE-2026-13491 is a denial of service vulnerability in the 78/xiaozhi-esp32 project through version 2.2.6. The flaw resides in the Application::GetInstance function within main/protocols/mqtt_protocol.cc, part of the MQTT Goodbye Handler component. Manipulation of the session_id argument in an inbound MQTT goodbye message triggers improper resource shutdown [CWE-404], causing the ESP32 device to enter a denial of service state. Exploitation occurs over the network and requires no authentication or user interaction, though attack complexity is high. A public exploit exists, and the upstream project has issued patch commit e182471f8c5a22434346bd98da34d3b66c8c8b3e.

Critical Impact

Remote attackers can send crafted MQTT goodbye messages containing malformed session_id values to disrupt availability of xiaozhi-esp32 IoT devices.

Affected Products

  • 78/xiaozhi-esp32 versions up to and including 2.2.6
  • Component: MQTT Goodbye Handler in main/protocols/mqtt_protocol.cc
  • ESP32-based devices running affected firmware builds

Discovery Timeline

  • 2026-06-28 - CVE-2026-13491 published to NVD
  • 2026-06-29 - Last updated in NVD database

Technical Details for CVE-2026-13491

Vulnerability Analysis

The vulnerability affects the MQTT protocol handler in xiaozhi-esp32, an ESP32-based voice assistant firmware. When the device receives an MQTT message with type set to goodbye, the handler parses the JSON payload and extracts the session_id field before comparing it against the stored session identifier. The original implementation dereferences the session_id->valuestring pointer without first verifying that the parsed cJSON node is actually a string.

If an attacker supplies a session_id field that is a non-string JSON type such as a number, boolean, array, or object, valuestring may point to invalid memory. The subsequent log call and string comparison operate on untrusted data, resulting in an improper shutdown or resource release condition [CWE-404] that terminates the MQTT session handler and disrupts device availability.

Root Cause

The root cause is missing input type validation on a cJSON-parsed field. The code trusted that session_id would always be a string when present, using only a null check rather than cJSON_IsString(). This assumption fails against attacker-controlled MQTT payloads.

Attack Vector

An attacker who can publish MQTT messages to the topic the device subscribes to — either by compromising or impersonating the MQTT broker, or by operating on the same broker with sufficient permissions — sends a crafted goodbye message. The malformed session_id value drives the device into a denial of service state. Attack complexity is high because the attacker must reach the MQTT channel and craft a payload that survives JSON parsing.

text
// Security patch in main/protocols/mqtt_protocol.cc
// Validate MQTT goodbye session id (#2023)
            ParseServerHello(root);
        } else if (strcmp(type->valuestring, "goodbye") == 0) {
            auto session_id = cJSON_GetObjectItem(root, "session_id");
-           ESP_LOGI(TAG, "Received goodbye message, session_id: %s", session_id ? session_id->valuestring : "null");
-           if (session_id == nullptr || session_id_ == session_id->valuestring) {
+           ESP_LOGI(TAG, "Received goodbye message, session_id: %s", cJSON_IsString(session_id) ? session_id->valuestring : "null");
+           if (cJSON_IsString(session_id) && session_id_ == session_id->valuestring) {
                auto alive = alive_;  // Capture alive flag
                Application::GetInstance().Schedule([this, alive]() {
                    if (*alive) {
// Source: https://github.com/78/xiaozhi-esp32/commit/e182471f8c5a22434346bd98da34d3b66c8c8b3e

The patch replaces the null check with cJSON_IsString(session_id), ensuring the code only dereferences valuestring after confirming the JSON node is a string.

Detection Methods for CVE-2026-13491

Indicators of Compromise

  • Unexpected device reboots or MQTT session terminations shortly after receiving goodbye messages.
  • MQTT broker logs showing goodbye messages with non-string session_id values (numbers, arrays, objects, or booleans).
  • Log entries containing Received goodbye message, session_id: null on firmware where the field was clearly populated by a client.

Detection Strategies

  • Inspect MQTT payloads targeting xiaozhi-esp32 topics for type: "goodbye" messages containing malformed session_id fields.
  • Monitor firmware serial or ESP-IDF logs for repeated crashes or watchdog resets tied to the MQTT tag.
  • Correlate broker-side publish events with device availability drops to identify targeted denial of service attempts.

Monitoring Recommendations

  • Enable MQTT broker access logging and retain publish payloads for topics consumed by ESP32 devices.
  • Alert on abnormal rates of goodbye message publishes to xiaozhi-esp32 subscribers.
  • Track device uptime and session churn to surface availability degradation.

How to Mitigate CVE-2026-13491

Immediate Actions Required

  • Update xiaozhi-esp32 firmware to a build containing commit e182471f8c5a22434346bd98da34d3b66c8c8b3e or later.
  • Restrict MQTT broker access so only trusted publishers can send messages to device topics.
  • Enforce MQTT authentication and TLS between devices and brokers to prevent unauthorized message injection.

Patch Information

The fix is available in the upstream repository via GitHub Commit e182471 and pull request PR #2023. See the tracking issue at GitHub Issue #2022 and additional analysis at VulDB CVE-2026-13491.

Workarounds

  • Configure broker ACLs to limit which clients may publish to xiaozhi-esp32 device topics.
  • Deploy MQTT topic filtering or a proxy that drops goodbye messages with non-string session_id fields.
  • Segment IoT devices onto isolated network zones to reduce broker exposure to untrusted clients.
bash
# Example Mosquitto ACL restricting publish rights on device topics
# /etc/mosquitto/acl.conf
user trusted-controller
topic write xiaozhi/+/control
topic write xiaozhi/+/goodbye

user device-fleet
topic read xiaozhi/+/control
topic read xiaozhi/+/goodbye

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.