CVE-2026-95842 — moquette-broker
Fix: moquette-io/moquette@86feb7cCVE-2026-95842 is a CWE-248 vulnerability in io.moquette:moquette-broker. A fix is available for io.moquette:moquette-broker — see the affected versions and patch details below.
Moquette uncaught MQTT command exceptions can terminate shared session event loops
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-95842.
EPSS Exploitation Probability
EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.
Real-World Exposure
io.moquette:moquette-brokerReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Maven packages — download data is not available via public APIs for these ecosystems.
Description
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
- (Critical) Bypass
pattern-based ACLs across tenants. InAuthorizationsCollector.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.)
-
(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.
-
(High) NPE in ACL sink on clientId # (invalid filter sensor/#/# -> null tokens -> Topic.match NPE at Topic.java:173).
-
(High) Will-message authorization bypass. Last-Will topic is published (PostOffice.publishWill) without canWrite/reserved-topic checks used for normal PUBLISH.
-
(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.
-
(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
- Reject clientId/username containing +/# (and / if structural) at CONNECT; expand %c/%u as literal tokens.
- Harden SessionEventLoop (catch Throwable + restart supervision) and validate $share filters.
- Apply authorization to Will publishes like normal PUBLISH.
- Add resource caps (connections, queues, retained, aliases, interceptor queue) + bounded session expiry.
- Separate H2 namespaces and fail closed on auth-class load failure.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| ☕Maven | io.moquette:moquette-broker | all versions | 0.18.1io.moquette:moquette-broker:0.18.1 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for io.moquette:moquette-broker, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update io.moquette:moquette-broker to 0.18.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-95842 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-95842 can be triaged on real exposure rather than presence alone.
Tailored to CVE-2026-95842. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is CVE-2026-95842 in your dependencies?
O3 Security finds CVE-2026-95842 across Maven dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.