CVE-2025-66168
Patch Available.
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Apache ActiveMQ (ActiveMQ Classic) is an open-source message broker, maintained by the Apache Software Foundation, for messaging and Enterprise Integration Patterns in Java. It supports JMS 1.1 and partially supports Jakarta Messaging, and speaks multiple wire protocols, including OpenWire, STOMP, AMQP 1.0, and MQTT. Its broker and client modules are published as Maven artifacts under org.apache.activemq.
An integer overflow vulnerability (CVE-2025-66168) has been identified in the MQTT transport of ActiveMQ, which allows authenticated MQTT clients to send a malformed Remaining Length field that overflows the computed frame length, causing the broker to misinterpret the payload as multiple MQTT control packets. Brokers that do not enable an MQTT transport connector are not impacted.
Per OWASP: Input validation checks whether data meets an application's requirements before the application uses it. It reduces the risk of malformed data, invalid business operations, and excessive resource consumption.
This issue affects multiple versions of ActiveMQ.
Details
Module Info
- Product: ActiveMQ
- Affected packages:
org.apache.activemq:activemq-mqtt,org.apache.activemq:activemq-all,org.apache.activemq:apache-activemq - Affected versions: <5.19.2, >=6.0.0 <6.1.9, >=6.2.0 <6.2.1
- GitHub repository: https://github.com/apache/activemq
- Published packages:
- Package manager: Maven
- Fixed in:
- OSS ActiveMQ 5.19.2, 6.2.4
- NES for ActiveMQ v5.16.10
Vulnerability Info
This High-severity vulnerability is found in the org.apache.activemq:activemq-mqtt package in multiple versions of ActiveMQ. Every MQTT control packet carries a Remaining Length field, a variable-length integer in which each byte contributes 7 bits and the high bit signals that another byte follows. The MQTT v3.1.1 specification limits this field to 4 bytes. ActiveMQ decodes it in two places, the NIO frame parser in MQTTCodec and the blocking MQTTWireFormat.unmarshal method, and neither counts how many length bytes it has consumed.
// MQTTCodec.variableLengthParser
digit = data.readByte();
length += (digit & 0x7F) * multiplier;
multiplier <<= 7;
if ((digit & 0x80) == 0) {
if (length == 0) {
processCommand();
currentParser = initializeHeaderParser();
} else {
if (length > getMaxFrameSize()) {
throw new IOException("The maximum message length was exceeded");
}
currentParser = initializeContentParser();
contentLength = length;
}
...
}// MQTTWireFormat.unmarshal
int multiplier = 1;
int length = 0;
do {
digit = dataIn.readByte();
length += (digit & 0x7F) * multiplier;
multiplier <<= 7;
}
while ((digit & 0x80) != 0);Both loops keep reading as long as the continuation bit is set. On the fifth byte, multiplier is 2^28, so (digit & 0x7F) * multiplier can exceed the 32-bit int range and length wraps around; after further shifts multiplier becomes 0 and extra bytes add nothing. A client can therefore choose length bytes whose wrapped sum is a small value that passes the getMaxFrameSize() check. The broker then reads only that many bytes as the packet body and parses the rest of the client's data as new MQTT control packets, so the frame boundaries the broker acts on differ from the ones the packet declared. This requires an established, authenticated MQTT connection.
Mitigation
Only recent versions of ActiveMQ are community-supported. Older lines are End-of-Life and will not receive public updates to address this issue. For more information see here.
Users of the affected components should apply one of the following mitigations:
- Upgrade to a currently supported ActiveMQ release line (5.19.x or 6.3.x) that contains the fix.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- Gai Tanaka (finder)