Moquette: Pattern-ACL wildcard injection (cross-tenant authorization bypass) plus a remote-unauthenticated DoS cluster, a Will-message authorization bypass, and a cross-session durable-corruption bug
moquette is reachable by untrusted MQTT clients (anonymous by default), so every byte from any client, including pre-authentication, is untrusted. This is a memory-safe JVM: the ceiling is authorization/ACL bypass + denial of service + cross-session integrity, **not RCE** (I did not find one and do not claim one). Audited at commit `da7f719a6bab9829d520b5838e13ea7b1f9be3ef`, module `broker/`. ## What a connecting client can do 1. (Critical) Bypass `pattern`-based ACLs across tenants. In `AuthorizationsCollector.canDoOperation` (AuthorizationsCollector.java:116-131, esp. line 123) the clientId/username is substituted raw into a pattern ACL rule and then wildcard-matched, and the clientId is never validated for MQTT wildcard characters +/# at CONNECT (MQTTConnection.processConnect): Topic substitutedTopic = new Topic(auth.topic.toString().replace("%c", client).replace("%u", username)); if (topic.match(substitutedTopic)) return true; A client that connects with clientId + turns sensor/%c/# into the filter sensor/+/#, gaining cross-tenant read AND write. (Precondition: pattern ACL rules configured — a common multi-tenant setup.) 2. (High) Crash the whole broker. SessionEventLoop (SessionEventLoop.java:40-54) catches only InterruptedException and is never restarted (SessionEventLoopGroup), so any uncaught exception on it wedges every co-located client. Trivially reachable inputs: malformed $share/grp SUBSCRIBE (SharedSubscriptionUtils.extractShareName -> StringIndexOutOfBoundsException), deeply nested topic (CTrie recursion -> StackOverflowError), and ACL NPE below. Unbounded subscriptions / retained / in-flight / topic-alias / interceptor state (BrokerInterceptor uses an unbounded queue) also allow OOM; durable stores allow disk exhaustion. 3. (High) NPE in ACL sink on clientId # (invalid filter sensor/#/# -> null tokens -> Topic.match NPE at Topic.java:173). 4. (High) Will-message authorization bypass. Last-Will topic is published (PostOffice.publishWill) without canWrite/reserved-topic checks used for normal PUBLISH. 5. (Medium) Cross-session durable corruption. H2PersistentQueue opens queue_"+clientId and queue_"+clientId+"_meta; client id sensor_meta collides with victim sensor metadata map -> corrupts head/tail. 6. (Medium) Fail-open if authenticator/authorizator class fails to load -> PermitAll/AcceptAll (Server.java:483-531). ## Proof of concept Source-only, no network; PoCs run on JDK 17: - PoCPatternAcl — clientId + gains cross-tenant read/write; clientId # triggers NPE - PoCSharedSubCrash — extractShareName("$share/grp") throws StringIndexOutOfBoundsException - PoCMapCollision — H2 MVStore collision overwrites victim metadata pointer ## Impact Cross-tenant eavesdropping and injection, whole-broker DoS, unauthorized Will publishes, and cross-session durable corruption. ## Remediation 1. Reject clientId/username containing +/# (and / if structural) at CONNECT; expand %c/%u as literal tokens. 2. Harden SessionEventLoop (catch Throwable + restart supervision) and validate $share filters. 3. Apply authorization to Will publishes like normal PUBLISH. 4. Add resource caps (connections, queues, retained, aliases, interceptor queue) + bounded session expiry. 5. Separate H2 namespaces and fail closed on auth-class load failure.
describes (8)
Related CVEs.
| ID | severity | exploitable | ||
|---|---|---|---|---|
| CVE-2026-95848US | critical9.1OT elevated | — | ||
Moquette is a lightweight Java MQTT broker. Prior to 0.18.1, when a configured authenticator or authorizator class cannot be loaded, Server.initializeAuthenticator and Server.initi… | ||||
| CVE-2026-95847US | high7.5OT elevated | — | ||
Moquette is a lightweight Java MQTT broker. Prior to 0.18.1, H2PersistentQueue derives a session's message-map name as queue_ plus the client ID and its metadata-map name as queue_… | ||||
| CVE-2026-95846US | high7.5OT elevated | — | ||
Moquette is a lightweight Java MQTT broker. Prior to 0.18.1, PostOffice.publishWill publishes a client's Last-Will message without applying the canWrite authorization and reserved-… | ||||
| CVE-2026-95845US | high7.5OT elevated | — | ||
Moquette is a lightweight Java MQTT broker. Prior to 0.18.1, the broker does not enforce a maximum length for pending per-session message queues. When a fast publisher sends messag… | ||||
| CVE-2026-95844US | high7.5OT elevated | — | ||
Moquette is a lightweight Java MQTT broker. Prior to 0.18.1, Moquette does not limit the depth of topic names and topic filters before processing them through recursive CTrie inser… | ||||
| CVE-2026-95843US | high7.5OT elevated | — | ||
Moquette is a lightweight Java MQTT broker. Prior to 0.18.1, PostOffice.subscribe parses a shared-subscription filter through SharedSubscriptionUtils.extractShareName before valida… | ||||
| CVE-2026-95842US | high7.5OT elevated | — | ||
Moquette is a lightweight Java MQTT broker. Prior to 0.18.1, SessionEventLoop.run catches only InterruptedException, and SessionEventLoopGroup does not restart a terminated loop. A… | ||||
| CVE-2026-85724US | —OT elevated | — | ||
Moquette is a lightweight Java MQTT broker. Prior to 0.18.1, when pattern-based ACL rules are configured, AuthorizationsCollector.canDoOperation substitutes client ID and username… | ||||
references
External citations — patches, advisories, analysis.
- https://github.com/moquette-io/moquettePACKAGE
- https://github.com/moquette-io/moquette/commit/14a2f4fd280c8f6a791600c306cbccecb7c67007WEB
- https://github.com/moquette-io/moquette/commit/26498631e92d50440b4e3ed42fa546253cc4090cWEB
- https://github.com/moquette-io/moquette/commit/72d6c8257191d2e4b2e3aa11ab25fd09f88c6cb7WEB
- https://github.com/moquette-io/moquette/commit/86feb7c31e6fac849c465d8079d08c0e7ef01cdfWEB
- https://github.com/moquette-io/moquette/commit/affdc71fdba92dc020421678970ae70518fb6da2WEB
- https://github.com/moquette-io/moquette/commit/b4a98bb3f3425ece476ed073aa080c627c1239afWEB
- https://github.com/moquette-io/moquette/commit/c65b3e90fa03e562e2c2fa69c3ee916c2cbfbd2bWEB
Advisories like this name the exposed products attackers go after on your perimeter. See what is exposed on your perimeter with a free passive scan.
Free scan