Quick Reference Summary
| Field | Details |
|---|---|
| CVE ID | CVE-2025-59946 |
| Vulnerability Name | NanoMQ Use-After-Free via Subscription Info List |
| CVSS v3.1 Score | 7.5 (High) |
| CVSS Vector | CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Severity | High |
| CWE Classification | CWE-416 (Use After Free) |
| Affected Product | NanoMQ MQTT Broker |
| Affected Versions | All versions earlier than 0.24.2 |
| Fixed Version | 0.24.2 (initial), 0.24.4 (complete fix) |
| Exploit Availability | Proof of Concept available (GitHub Issue #1863) |
| Exploitability | Remote (network-accessible) |
| Attack Complexity | High (race condition timing required) |
| Privileges Required | Low (authenticated MQTT client) |
| User Interaction | None |
| Vendor | EMQ Technologies Inc. / NanoMQ Project |
| GitHub Advisory | GHSA-xg37-23w7-72p5 |
| Published Date | December 27, 2025 |
Vulnerability Overview
This issue impacts the NanoMQ MQTT Broker, an ultra-lightweight, high-performance broker designed primarily for IoT edge environments and Software-Defined Vehicles (SDV). NanoMQ is built on top of the NNG asynchronous I/O framework and uses an actor-based, multi-threaded architecture. It is widely deployed in edge scenarios where performance and minimal resource usage are critical.
At its core, the vulnerability is a classic race condition in the handling of subscription information (“sub info”) lists. Under concurrent access, improper synchronization allows one thread to free memory while another thread continues to reference it. This results in a heap use-after-free condition that can cause crashes or other undefined behavior.
Technical Deep Dive
What Is a Use-After-Free Vulnerability (CWE-416)?
A use-after-free vulnerability occurs when an application continues to access memory after it has already been released. Freed memory may later be reused for other allocations. If stale pointers are still used, the program can crash, corrupt memory, or—under certain conditions—allow an attacker to manipulate execution flow by influencing what data is placed in the reused memory region.
Root Cause Analysis
The root cause lies in how NanoMQ manages subscription information across multiple threads. The broker relies on an actor-based concurrency model inherited from the NNG library to handle many MQTT clients simultaneously. The flaw appears in the transport and subscription handling paths, specifically within the following components:
- broker_tcp.c – MQTT TCP transport handling
- broker_tls.c – TLS/SSL transport handling
- sub_handler.c – Subscription management logic
- message.c – Message processing and memory handling
When clients rapidly subscribe and unsubscribe—or when many clients perform subscription operations concurrently—a race window can open. During this window, one thread may free a subscription data structure while another thread is still accessing it. The result is a heap use-after-free that typically manifests as a crash.
Race Condition Mechanics
The race condition generally follows this sequence:
- Thread A begins handling a subscription request and retrieves a reference to the subscription info list
- Thread B concurrently processes an unsubscribe request or client disconnect
- Thread B frees memory associated with one or more subscription entries
- Thread A, still holding a stale pointer, attempts to read from or write to the freed memory
- The broker crashes or exhibits undefined behavior
The AddressSanitizer output included in the original report clearly reflects this pattern:
ERROR: AddressSanitizer: heap-use-after-free on address 0x60f00000830c
WRITE of size 4 at 0x60f00000830c thread T8
Exploitation Scenarios
Attack Overview
An attacker with basic MQTT client access can abuse this vulnerability to trigger a denial-of-service condition. The general attack flow is as follows:
- Connect to the Broker – The attacker establishes a normal MQTT client connection
- Trigger High-Frequency Subscription Changes – Rapidly issues SUBSCRIBE and UNSUBSCRIBE requests, or sends malformed MQTT packets
- Hit the Race Window – Carefully timed or high-volume requests increase the chance of triggering the race condition
- Crash the Broker – The use-after-free condition causes NanoMQ to terminate, disconnecting all clients
Proof of Concept
A public proof of concept is available in GitHub Issue #1863. The PoC involves sending specially crafted, hex-encoded MQTT packets to port 1883. When repeated, these packets can reliably crash the broker:
echo <hex_payload> | xxd -r -p | nc 127.0.0.1 1883
Researchers observed that the resulting crash stack traces can vary between executions, which is typical for race-condition vulnerabilities where thread timing influences the failure point.
Impact Assessment
| Impact Area | Severity | Description |
|---|---|---|
| Availability | High | Broker crash leading to full service disruption |
| Confidentiality | High | Potential memory disclosure with refined exploitation |
| Integrity | High | Memory corruption may affect data integrity |
In real-world IoT or IIoT deployments, a broker crash can have serious consequences, including:
- Loss of connectivity for all sensors and actuators
- Disruption of data pipelines feeding upstream systems or cloud services
- Potential data loss if message persistence is not enabled
- Manual intervention required to restore service
MITRE ATT&CK Mapping
| Tactic | Technique ID | Technique Name | Description |
|---|---|---|---|
| Impact | T1499 | Endpoint Denial of Service | Crashing the MQTT broker to disrupt all clients |
| Impact | T1499.004 | Application or System Exploitation | Exploiting a software flaw to cause DoS |
| Initial Access | T1190 | Exploit Public-Facing Application | Targeting exposed NanoMQ brokers |
| Execution | T1203 | Exploitation for Client Execution | Triggering the flaw via crafted packets |
Detection Strategies
Relevant Log Sources
| Log Source | Purpose | Priority |
|---|---|---|
| NanoMQ Application Logs | Detect crashes, errors, and abnormal exits | High |
| System Logs (syslog/journald) | Capture segmentation faults and core dumps | High |
| Network Logs / PCAP | Identify abnormal MQTT traffic patterns | Medium |
| Process Monitoring | Track unexpected NanoMQ restarts | Medium |
| Memory Monitoring | Observe anomalies before crashes | Low |
Indicators of Compromise
Process-Level Indicators
- NanoMQ terminating with SIGSEGV (signal 11)
- Core dump files generated
- Repeated restarts by systemd or other supervisors
- Log messages referencing heap-use-after-free or AddressSanitizer
Network-Level Indicators
- Excessive SUBSCRIBE/UNSUBSCRIBE traffic from a single source
- Malformed MQTT packets
- Rapid connection churn using the same client IDs
- High connection rates to ports 1883 or 8883
Detection Rules
Splunk Detection Rule
index=linux sourcetype=syslog
(process="nanomq" OR message="*nanomq*")
("segfault" OR "SIGSEGV" OR "heap-use-after-free" OR "terminated")
| stats count by _time, host, message
| where count > 0
Microsoft Sentinel (KQL) Detection Rules
// Detect NanoMQ process crashes
Syslog
| where ProcessName contains "nanomq" or SyslogMessage contains "nanomq"
| where SyslogMessage contains "segfault"
or SyslogMessage contains "SIGSEGV"
or SyslogMessage contains "heap-use-after-free"
or SyslogMessage contains "terminated"
| project TimeGenerated, Computer, ProcessName, SyslogMessage
| order by TimeGenerated desc
// Detect abnormal MQTT connection patterns
AzureNetworkAnalytics_CL
| where DestPort_d == 1883 or DestPort_d == 8883
| summarize ConnectionCount = count()
by bin(TimeGenerated, 1m), SrcIP_s
| where ConnectionCount > 100
| project TimeGenerated, SrcIP_s, ConnectionCount
Auditd Rule
-w /usr/bin/nanomq -p x -k nanomq_execution
-w /var/log/nanomq -p wa -k nanomq_logs
Remediation and Mitigation
Immediate Actions
- Upgrade NanoMQ to version 0.24.4 or newer (0.24.6 recommended)
apt-get update && apt-get upgrade nanomq
git clone https://github.com/nanomq/nanomq.git
cd nanomq
git checkout 0.24.6
mkdir build && cd build
cmake ..
make
sudo make install
- Temporary Mitigations (if upgrading is not immediately possible):
- Throttle subscription and unsubscription rates
- Apply network-level connection rate limiting
- Enable automatic broker restarts with monitoring alerts
- Note that typical deployments may be less exposed, as most clients do not perform high-frequency sub/unsub operations
Network Hardening
- Enforce connection and request rate limits
- Restrict broker exposure through segmentation or firewalls
- Require TLS and client authentication
- Deploy IDS/IPS signatures for abnormal MQTT behavior
Monitoring Recommendations
- Alert on unexpected NanoMQ restarts
- Centralize and analyze crash logs
- Monitor MQTT traffic patterns for anomalies
- Enable core dump collection for forensic analysis
Patch and Advisory Information
| Resource | Link |
|---|---|
| GitHub Security Advisory | https://github.com/nanomq/nanomq/security/advisories/GHSA-xg37-23w7-72p5 |
| Bug Report | https://github.com/nanomq/nanomq/issues/1863 |
| Initial Patch (0.24.2) | https://github.com/nanomq/nanomq/releases/tag/0.24.2 |
| Complete Fix (0.24.4) | https://github.com/nanomq/nanomq/releases/tag/0.24.4 |
| Latest Release | https://github.com/nanomq/nanomq/releases/latest |
| Downloads | https://nanomq.io/downloads |
Version History and Fix Timeline
| Version | Date | Status |
|---|---|---|
| < 0.24.2 | Pre–Aug 2024 | Vulnerable |
| 0.24.2 | Aug 26, 2024 | Initial (partial) fix |
| 0.24.3 | Sep 15, 2024 | Additional refactoring |
| 0.24.4 | Sep 22, 2024 | Full fix for race condition |
| 0.24.5 | Oct 29, 2024 | Security updates |
| 0.24.6 | Nov 22, 2024 | Current stable release |
Additional Context
About NanoMQ
NanoMQ is an open-source, ultra-lightweight MQTT broker developed by EMQ Technologies under the MIT license. It is designed specifically for edge computing use cases and offers:
- Implementation in pure C for portability and performance
- Actor-based asynchronous I/O via NNG
- Support for MQTT 3.1.1 and MQTT 5.0
- MQTT over QUIC support
- Compatibility with Linux, Windows, and macOS
- Support for x86_64, ARM, MIPS, and RISC-V
- Extremely small memory footprint (as low as ~200 KB at startup)
Related Historical Issues
NanoMQ has previously experienced similar race-condition and use-after-free bugs, including issues related to:
- Webhook publish event handling (Issue #527)
- SUBACK reply processing (Issue #572)
- Retained message handling over TLS (NanoNNG Issue #230)
These issues highlight the inherent complexity of memory safety in highly concurrent, performance-focused C applications.
Final Takeway
This vulnerability highlights a common challenge in high-performance, multi-threaded C software: ensuring correct memory ownership and synchronization under concurrency. While the most practical impact here is denial of service, use-after-free bugs can sometimes be escalated to remote code execution if memory reuse can be reliably controlled.
Organizations relying on NanoMQ in production—particularly in critical IoT or industrial environments—should prioritize patching. The combination of low access requirements and high availability impact makes this a non-trivial risk.
The NanoMQ maintainers have responded promptly, releasing multiple iterations to fully address the issue. Deploying the latest stable version (0.24.6) is strongly recommended.
