Sep 23, 2026·7 min read·2 visits
A critical flaw in Moquette versions < 0.18.1 allows remote clients to inject MQTT wildcards into their Client ID or username, bypassing pattern-based ACLs for cross-tenant topic access, or triggering a NullPointerException that silences the shared event loop and crashes the broker's session handling.
CVE-2026-85724 is a critical vulnerability in the Moquette MQTT broker (versions prior to 0.18.1) where unvalidated substitution of client identifiers and usernames into pattern-based Access Control Lists (ACLs) permits remote authenticated attackers to bypass multi-tenant boundaries and trigger a Denial of Service.
Moquette is a lightweight, Java-based MQTT broker widely deployed in industrial internet-of-things (IIoT) architectures, embedded software applications, and microservice backends. To support multitenancy, Moquette implements a pattern-based Access Control List (ACL) system. This system allows administrators to define dynamic topic templates where placeholders like %c and %u are dynamically replaced by the client ID and username of the active session. This mechanism is designed to isolate tenants within their respective logical namespaces, ensuring that a client can only publish or subscribe to topics specifically registered to their identity.
The attack surface for this vulnerability is exposed during the client connection processing and topic validation phases. The root issue belongs to the CWE-863 (Incorrect Authorization) and CWE-155 (Improper Neutralization of Wildcards or Matching Symbols) categories. Because the broker did not sanitize or inspect the provided connection parameters before performing string replacement, a low-privilege remote client could intentionally inject MQTT wildcard characters into its identity fields.
Exploitation of this vulnerability results in a total breakdown of multi-tenant isolation. Attackers can gain complete read and write access to unauthorized namespaces, enabling them to harvest sensitive data or publish malicious control messages. Additionally, crafted identities can trigger a secondary crash vector inside the session processing thread, leading to a persistent Denial of Service (DoS) for all clients sharing the affected event loop.
The vulnerability resides in the core authorization evaluation pipeline located inside io.moquette.broker.security.AuthorizationsCollector.java within the canDoOperation method. When a client requests access to an MQTT topic, the broker iterates over the parsed pattern-based authorization configurations. For each configuration, the broker calls a string substitution routine to construct the compiled target topic filter. The template replacement statement is implemented as follows:
Topic substitutedTopic = new Topic(auth.topic.toString().replace("%c", client).replace("%u", username));
This implementation operates on the assumption that client IDs and usernames are safe, pre-validated string literals. In standard MQTT environments, however, the characters + (single-level wildcard) and # (multi-level wildcard) possess specific semantic matching capabilities. The broker failed to execute any escaping, sanitization, or syntactic restriction on the incoming client and username variables before applying this replacement.
When a client connects with a wildcard string like + as its client ID, the placeholder %c in a rule like sensor/%c/# is substituted directly. This transforms the restricted rule into sensor/+/#. The resulting compiled filter allows the connection to match any topic structure matching the pattern, breaching the intended isolation boundaries. If an attacker injects a multi-level wildcard #, the pattern expands to sensor/#/#. Under the MQTT protocol specification, a multi-level wildcard must be terminal. Parsing this invalid structure yields empty internal tokens inside the constructed Topic instance, leading to subsequent fatal runtime failures.
The vulnerability was mitigated in version 0.18.1 across several focused patches. In the initial vulnerable version, AuthorizationsCollector.java processed the replacement blindly. The fix implemented in commit b4a98bb3f3425ece476ed073aa080c627c1239af introduces strict pattern validation before executing the template substitution:
// Introduced helper method to detect injected wildcards
private static boolean hasTopicWildcard(String identity) {
return identity != null && (identity.indexOf('+') >= 0 || identity.indexOf('#') >= 0);
}Within the authorization block, the code now checks both connection parameters before allowing substitution. If wildcards are present, the broker logs a security warning and bypasses the evaluation block entirely, causing the authorization logic to fail closed:
if (isNotEmpty(client) || isNotEmpty(username)) {
if (hasTopicWildcard(client) || hasTopicWildcard(username)) {
LOG.warn("Skipping pattern ACL matching: the client id or username contains MQTT topic " +
"wildcards ('+' or '#') and can't be safely substituted into a pattern filter " +
"(client: {}, username: {})", client, username);
} else {
// Original substitution path executing only on sanitized parameters
for (Authorization auth : m_patternAuthorizations) {
Topic substitutedTopic = new Topic(auth.topic.toString().replace("%c", client).replace("%u", username));
if (auth.grant(permission)) {
if (topic.match(substitutedTopic)) {
return true;
}
}
}
}
}A secondary flaw addressed in commit ffd921523d66740c1a4e35918891dd4ced227769 targets anonymous connections. If a client connects without authentication, the username parameter resolves to a Java null. Calling .replace("%u", username) on a null variable throws a NullPointerException. The patch safely normalizes these inputs prior to string operations:
final String clientValue = client == null ? "" : client;
final String usernameValue = username == null ? "" : username;To exploit the authorization bypass vector, an attacker must establish a standard MQTT connection to the broker. This requires low-privilege client credentials or access to an anonymous port if permitted by the broker's configuration. The target system must also have pattern-based ACL rules active, such as tenant/%c/telemetry.
The attacker initiates a connection using the client ID +. Once the connection is accepted, the attacker issues a subscription request to the broad wildcard path tenant/+/telemetry. When the broker processes this subscription request, it evaluates the pattern rule. The substitution converts tenant/%c/telemetry to tenant/+/telemetry. Because the substituted pattern is identical to the target subscription path, the broker validates the request, granting the attacker read access to all telemetry messages generated across all tenant namespaces.
The vulnerability is highly reproducible. Security researchers can verify this behavior utilizing standard test suites or command-line MQTT utilities. By passing a wildcard identity during the connection phase, an attacker can confirm whether they receive data originating from other isolated test channels.
The secondary exploitation vector targets broker availability. If an attacker initiates a connection with the client ID set to #, the pattern substitution outputs tenant/#/#. When the broker attempts to parse this malformed path inside the Topic parser, it constructs a flawed topic object with no valid internal tokens.
When the system subsequently executes topic.match(substitutedTopic) to compare the client's request against the ACL, the method fails internally. The execution of Topic.match() crashes with an unhandled NullPointerException (NPE). In Moquette versions prior to 0.18.1, these exceptions were handled poorly by the underlying thread infrastructure.
The executing context for these sessions is managed by SessionEventLoop.java. The event loop only caught InterruptedException. When the unhandled NullPointerException occurred, it propagated directly to the top-level handler, silently terminating the shared event loop thread. Because Moquette multiplexes multiple active client sessions across a limited thread pool, killing one of these loop threads wedges all co-located sessions, leading to a complete and persistent Denial of Service.
Remediation requires upgrading the Moquette broker to version 0.18.1 or newer. This update integrates the necessary wildcard parameter validation inside AuthorizationsCollector.java and incorporates robust exception containment inside SessionEventLoop.java (via commit 86feb7c31e6fac849c465d8079d08c0e7ef01cdf). The thread execution path is now protected by a generic Throwable catch block, preventing runtime errors from killing the shared loops.
If upgrading the dependency is not immediately feasible, administrators can apply several defense-in-depth mitigations. First, configure the broker or an upstream load balancer to reject client identifiers containing the characters + or # during the connection phase. Second, disable pattern-based ACLs in configurations where tenant separation is strictly required, opting instead for explicit static rules mapped per authenticated user.
Monitoring and detection can be configured by auditing the broker's logs. The patched version of Moquette explicitly logs skipped pattern evaluations. System administrators should configure alerting rules for log lines matching: Skipping pattern ACL matching: the client id or username contains MQTT topic wildcards. The appearance of this warning is a strong indicator of either a misconfigured client or an active exploitation attempt.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Moquette moquette-io | < 0.18.1 | 0.18.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-863, CWE-155 |
| Attack Vector | Network (Unauthenticated or Low-Privilege Remote) |
| CVSS v3.1 Score | 9.6 (Critical) |
| EPSS Score | N/A |
| Impact | Cross-Tenant Authorization Bypass & Denial of Service |
| Exploit Status | Proof of Concept / Code-Level Analysis |
| KEV Status | Not Listed in CISA KEV Catalog |
The software performs authorization checks but fails to prevent a user from gaining unauthorized access via malicious client configurations.
A Cross-Site Request Forgery (CSRF) vulnerability in REDAXO CMS prior to version 5.21.2 allows unauthenticated remote attackers to trigger unauthorized package updates by exploiting an insecure default configuration in the base API class.
CVE-2026-88974 is an incorrect authorization vulnerability in the WPGraphQL plugin for WordPress. Due to a failure to perform object-level capability checks or validate status-transition requirements in the updatePost mutation handler, authenticated Contributor-level users can publish their own draft posts without editorial approval or modify their previously published posts.
A technical analysis of CVE-2026-73858 / GHSA-gxrg-x694-283w, a server-side template injection vulnerability in the Solspace Freeform plugin for Craft CMS. The vulnerability permits unauthenticated users to trigger dynamic Twig evaluation of input fields during form validation re-rendering, causing local directory path disclosure and PHP runtime information exposure.
An algorithmic complexity vulnerability (CWE-407) in the query decoder of the Elixir Plug library (CVE-2026-54892) allows unauthenticated remote attackers to trigger scheduler starvation and denial of service by transmitting deeply nested brackets in query parameters or URL-encoded post bodies.
CVE-2026-83801 is a stored Cross-Site Scripting (XSS) vulnerability in Nautobot. The vulnerability arises because the application interpolates user-controlled database properties—specifically Relationship descriptions and Module Family names—directly into the help_text parameter of Django form fields. These fields are rendered using Django's |safe filter, bypassing HTML escaping and enabling persistent injection. When an administrative user accesses the affected forms, the payload executes contextually in their browser. This allows attackers to hijack active sessions and perform unauthorized operations. Nautobot versions prior to v2.4.37 and v3.1.8 are affected by this vulnerability. The issue has been patched by implementing contextual HTML escaping and strict markdown sanitization.
An authorization bypass vulnerability exists in Nautobot's REST API endpoints handling approval workflows. Due to an architectural inconsistency, a standalone, generic REST API endpoint for creating approval responses was exposed without propagating the required business-logic validations. This allows low-privileged authenticated users to submit forged, self-approved votes, bypassing approval thresholds and triggering unauthorized server-side automated jobs.