CVE-2025-59946: When Subscription Races Take Down NanoMQ

Quick Reference Summary

FieldDetails
CVE IDCVE-2025-59946
Vulnerability NameNanoMQ Use-After-Free via Subscription Info List
CVSS v3.1 Score7.5 (High)
CVSS VectorCVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
SeverityHigh
CWE ClassificationCWE-416 (Use After Free)
Affected ProductNanoMQ MQTT Broker
Affected VersionsAll versions earlier than 0.24.2
Fixed Version0.24.2 (initial), 0.24.4 (complete fix)
Exploit AvailabilityProof of Concept available (GitHub Issue #1863)
ExploitabilityRemote (network-accessible)
Attack ComplexityHigh (race condition timing required)
Privileges RequiredLow (authenticated MQTT client)
User InteractionNone
VendorEMQ Technologies Inc. / NanoMQ Project
GitHub AdvisoryGHSA-xg37-23w7-72p5
Published DateDecember 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:

  1. Thread A begins handling a subscription request and retrieves a reference to the subscription info list
  2. Thread B concurrently processes an unsubscribe request or client disconnect
  3. Thread B frees memory associated with one or more subscription entries
  4. Thread A, still holding a stale pointer, attempts to read from or write to the freed memory
  5. 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:

  1. Connect to the Broker – The attacker establishes a normal MQTT client connection
  2. Trigger High-Frequency Subscription Changes – Rapidly issues SUBSCRIBE and UNSUBSCRIBE requests, or sends malformed MQTT packets
  3. Hit the Race Window – Carefully timed or high-volume requests increase the chance of triggering the race condition
  4. 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 AreaSeverityDescription
AvailabilityHighBroker crash leading to full service disruption
ConfidentialityHighPotential memory disclosure with refined exploitation
IntegrityHighMemory 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

TacticTechnique IDTechnique NameDescription
ImpactT1499Endpoint Denial of ServiceCrashing the MQTT broker to disrupt all clients
ImpactT1499.004Application or System ExploitationExploiting a software flaw to cause DoS
Initial AccessT1190Exploit Public-Facing ApplicationTargeting exposed NanoMQ brokers
ExecutionT1203Exploitation for Client ExecutionTriggering the flaw via crafted packets

Detection Strategies

Relevant Log Sources

Log SourcePurposePriority
NanoMQ Application LogsDetect crashes, errors, and abnormal exitsHigh
System Logs (syslog/journald)Capture segmentation faults and core dumpsHigh
Network Logs / PCAPIdentify abnormal MQTT traffic patternsMedium
Process MonitoringTrack unexpected NanoMQ restartsMedium
Memory MonitoringObserve anomalies before crashesLow

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

  1. 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
  1. 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

ResourceLink
GitHub Security Advisoryhttps://github.com/nanomq/nanomq/security/advisories/GHSA-xg37-23w7-72p5
Bug Reporthttps://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 Releasehttps://github.com/nanomq/nanomq/releases/latest
Downloadshttps://nanomq.io/downloads

Version History and Fix Timeline

VersionDateStatus
< 0.24.2Pre–Aug 2024Vulnerable
0.24.2Aug 26, 2024Initial (partial) fix
0.24.3Sep 15, 2024Additional refactoring
0.24.4Sep 22, 2024Full fix for race condition
0.24.5Oct 29, 2024Security updates
0.24.6Nov 22, 2024Current 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.


Aegiron

Backed by 11+ years in cybersecurity and incident response, we decode the latest threats shaping today’s digital battlefield. This blog cuts through the noise with clear insights on vulnerabilities, emerging exploits, and the cyber news defenders can’t afford to miss.