← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-41044 · CWE-20 · Disclosed 2026-04-24

Improper Input Validation

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a loaded nail gun locked in the server room, not a sniper round from the internet

CVE-2026-41044 is a broker-side RCE in Apache ActiveMQ Classic where an authenticated user can abuse the admin web console and Jolokia-exposed DestinationView MBean to smuggle an xbean-style broker name, trigger a VM transport, and make the broker JVM load attacker-controlled remote Spring XML. Affected ranges are all 5.x before 5.19.6 and 6.0.0 through 6.2.4 across apache-activemq, activemq-broker, and activemq-all.

paragraph 2: Vendor severity is defensible in a lab because the end state is full JVM code execution, but it overstates the real-world enterprise urgency. The decisive friction is that the attacker must first reach and authenticate to the management plane—the web console/Jolokia path—not merely the broker listener, and the vendor docs place those interfaces at localhost:8161 by default; that sharply narrows exposed population, which lines up with the tiny EPSS and lack of KEV or public exploitation evidence.

"This is real RCE, but it starts on an authenticated management plane, not from the open internet."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Reach the admin surface with browser or curl

The attacker needs access to the ActiveMQ Classic web console or its Jolokia-backed management API on port 8161. This is not the normal client messaging path on 61616; it is the broker administration path used for monitoring and management operations.
Conditions required:
  • Network reachability to the web console / Jolokia endpoint
  • ActiveMQ Classic web apps enabled
  • Attacker can reach TCP 8161 directly or through a proxy
Where this breaks in practice:
  • Vendor docs show the console and Jolokia examples on localhost:8161, so many deployments keep it internal
  • A lot of enterprises segment broker admin ports away from user networks and the internet
  • Public-facing exposure usually requires an explicit reverse proxy, NAT, or firewall exception
Detection/coverage: External scanners often miss this if 8161 is internal-only. Exposure discovery should key on :8161/admin and :8161/api/jolokia; version detection is covered by Nessus plugin 311265 when the product version is visible.
STEP 02

Authenticate to the console / Jolokia

The bug is not pre-auth. The attacker must hold valid credentials accepted by the web console realm or any upstream auth protecting Jolokia, then perform management actions that let them plant a malicious broker name containing an xbean binding.
Conditions required:
  • Valid credentials for the admin web application or equivalent management access
  • Jolokia requests permitted after authentication
Where this breaks in practice:
  • Credential theft, password reuse, default creds, or prior foothold are all separate attacker work
  • Modern SSO, PAM-backed auth, vault-managed secrets, and admin jump hosts materially reduce reachability
  • If the service is only reachable from admin networks, this is already a post-initial-access path
Detection/coverage: Look for successful auth to /admin or /api/jolokia from unusual hosts, service accounts, or non-admin user segments. Web logs and reverse proxies should show the source IP even if the broker itself does not.
STEP 03

Abuse DestinationView via Jolokia POST

With access in hand, the attacker uses the admin page workflow and/or direct Jolokia operations to create a malicious broker name, then calls the DestinationView MBean to send a message that forces VM transport creation referencing that crafted name. This is the key weaponization step: the management feature becomes the trigger that dereferences attacker-controlled transport metadata.
Conditions required:
  • Authenticated management access remains active
  • Relevant ActiveMQ MBeans are exposed through Jolokia
  • The attacker can issue POST requests to Jolokia or equivalent console actions
Where this breaks in practice:
  • This is not commodity one-shot RCE against a random listener; it depends on a specific management workflow
  • Custom Jolokia policy restrictions can break the chain if exec operations are narrowed
  • Some environments monitor or alert on unusual Jolokia exec activity
Detection/coverage: Hunt for POST /api/jolokia requests invoking ActiveMQ MBeans, especially DestinationView operations and suspicious broker names containing xbean, remote URIs, or transport parameters.
STEP 04

Broker loads remote Spring XML and executes on the JVM

The VM transport resolves the malicious broker configuration and Spring's ResourceXmlApplicationContext instantiates singleton beans before BrokerService finishes validating the configuration. That ordering flaw is what turns config abuse into code execution, including bean factory methods that can reach Runtime.exec().
Conditions required:
  • Broker can resolve the attacker-supplied remote Spring XML location
  • The vulnerable version range is present
Where this breaks in practice:
  • Outbound network controls can block remote XML retrieval and kill many practical exploit paths
  • If the broker has no egress to untrusted destinations, exploit reliability drops hard
  • EDR may still catch the payload stage even if it cannot prevent the Spring bean instantiation
Detection/coverage: Watch broker egress to unusual HTTP(S) endpoints immediately after Jolokia activity, JVM child-process creation from the broker process, and unexpected classpath / Spring context loads. Version-only checks: Nessus 311265; distro package presence without a backport: Nessus 310128.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo reviewed source showed active exploitation, and CISA KEV did not list CVE-2026-41044 when checked against the catalog on 2026-05-29.
Proof-of-concept availabilityNo public PoC or Metasploit module was found in the reviewed sources; Tenable also marked exploit availability as "No known exploits are available." *This is an inference from the sources reviewed, not proof that no private exploit exists.*
EPSSReviewer-supplied EPSS is 0.00073. That is extremely low and consistent with a management-plane, post-auth bug; one public aggregator places it around the low-20s percentile *but that percentile was not confirmed from a primary FIRST feed in the reviewed sources*.
KEV statusNot KEV-listed as of 2026-05-29. Contrast that with the related ActiveMQ flaw CVE-2026-34197, which *has* KEV history—useful context that defenders should not blindly treat every Jolokia-related ActiveMQ CVE as equally urgent.
CVSS meaningCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H models easy exploitation *after* low privileges are obtained. The inflation comes from CVSS treating authenticated management access as only PR:L, while defenders know that access usually implies prior compromise, credential theft, or a very exposed admin plane.
Affected versionsapache-activemq, activemq-broker, and activemq-all are affected in all versions before 5.19.6 and 6.0.0 through 6.2.4.
Fixed versions / backportsVendor fixes are 5.19.6 and 6.2.5. In the reviewed distro advisories, Ubuntu still showed Needs evaluation rather than a published backport, so do not assume distro packaging has quietly fixed this yet.
Exposure realityActiveMQ docs show the web console at http://localhost:8161/admin and the Jolokia management API at http://localhost:8161/api/jolokia/ by default. That means the exposed population is usually far smaller than a generic network RCE against the broker's client listener.
DisclosurePublicly disclosed 2026-04-24; Apache shipped the fixing releases 2026-04-23.
Researcher / creditVendor advisory credits jsjcw as the finder.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (6.6/10)

The single most important downward pressure is that exploitation starts with authenticated access to the broker management plane, not with a blind shot at the normal messaging listener. That prerequisite implies either prior compromise, exposed admin infrastructure, or credential theft, which dramatically shrinks the reachable population despite the severe technical impact.

HIGH Exploitation requires authenticated access to the web console / Jolokia management plane
MEDIUM Real-world exposure prevalence is lower than CVSS implies because docs place management endpoints on localhost, but enterprise customizations vary
HIGH Current threat pressure is low: no KEV listing, no public exploitation evidence in reviewed sources, tiny EPSS

Why this verdict

  • Downgrade for attacker position: PR:L here really means *authenticated management access*. In enterprise terms that usually implies prior foothold, stolen creds, or an intentionally exposed admin plane, so I cut materially below the vendor 8.8 baseline.
  • Downgrade for reachable population: the vulnerable surface is the web console / Jolokia path on port 8161, not the ordinary broker traffic path. Vendor docs use localhost:8161 for both admin and Jolokia examples, which means a lot of estates will have little or no internet-exposed population.
  • Keep it above LOW: once the chain is satisfied, impact is full broker JVM RCE with the potential to pivot through messaging infrastructure, secrets, and integration paths. This is still a serious post-auth compromise of a high-value service.

Why not higher?

There is no evidence in the reviewed sources of active exploitation, KEV status, or broadly available public weaponization. More importantly, the bug is gated by access to an authenticated management interface, which is a compounding friction point that CVSS under-penalizes in real enterprise environments.

Why not lower?

This is not a harmless admin bug or a narrow information leak: successful exploitation gives arbitrary code execution on the broker JVM. ActiveMQ brokers often sit on trusted internal paths and handle sensitive traffic, so when an attacker already has console access the blast radius can be meaningful.

05 · Compensating Control

What to do — in priority order.

  1. Fence off port 8161 — Restrict the web console and /api/jolokia to admin jump hosts, VPN ranges, or a management VLAN only. For a MEDIUM verdict there is no mitigation SLA, but if any broker exposes 8161 beyond an admin enclave, close that gap immediately and still complete patching inside the 365-day remediation window.
  2. Kill default and shared credentials — Rotate any local jetty-realm.properties credentials, remove admin/admin anywhere it still exists, and move to unique admin identities. This breaks the cheapest path into the management plane and should be done opportunistically now even though MEDIUM has no mitigation SLA.
  3. Tighten Jolokia policy — Use a custom Jolokia security policy to narrow or deny dangerous MBean operations rather than leaving broad exec access over org.apache.activemq:*. This directly attacks the exploit chain and is the best compensating control when you cannot patch immediately.
  4. Block broker egress to untrusted URLs — The exploit path wants the broker to fetch attacker-controlled remote Spring XML. Enforce outbound allowlisting or at least deny direct internet egress from broker hosts so a planted malicious broker name cannot easily dereference external content.
  5. Alert on Jolokia exec abuse — Create detections for POST /api/jolokia requests invoking ActiveMQ MBeans, especially DestinationView actions and suspicious strings like xbean, remote URLs, and transport parameters. This is cheap telemetry that catches both this bug and adjacent Jolokia abuse families.
What doesn't work
  • A WAF alone is weak here because many exploit paths are internal-only or come from already-authenticated admin sessions; the decisive control is network segmentation and auth hardening, not generic edge filtering.
  • TLS only does nothing once the attacker is authenticated; encryption protects transit, not dangerous MBean operations.
  • EDR alone is not enough. It may catch child-process execution or payload staging, but it does not remove the vulnerable management feature chain that leads to broker compromise.
  • Focusing only on port 61616 misses the problem. This CVE rides the admin console / Jolokia path on 8161, not normal client messaging.
06 · Verification

Crowdsourced verification payload.

Run this on the target ActiveMQ host or against an extracted install directory. Invoke it as python3 verify_cve_2026_41044.py /opt/activemq or point it at a JAR like python3 verify_cve_2026_41044.py /opt/activemq/lib/activemq-broker-6.2.4.jar; no admin rights are required if the install path is readable.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# verify_cve_2026_41044.py
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=USAGE

import os
import re
import sys
import zipfile
import subprocess
from pathlib import Path

USAGE = "Usage: python3 verify_cve_2026_41044.py <ACTIVEMQ_HOME|jar-file|version-string>"


def norm_version(v):
    if not v:
        return None
    v = v.strip()
    m = re.search(r'(\d+)\.(\d+)\.(\d+)', v)
    if not m:
        return None
    return tuple(int(x) for x in m.groups())


def version_to_str(vt):
    return '.'.join(str(x) for x in vt) if vt else 'unknown'


def compare(a, b):
    return (a > b) - (a < b)


def is_vulnerable(vt):
    if vt is None:
        return None
    if compare(vt, (6, 0, 0)) >= 0 and compare(vt, (6, 2, 5)) < 0:
        return True
    if compare(vt, (5, 19, 6)) < 0:
        return True
    return False


def read_manifest_version(jar_path):
    try:
        with zipfile.ZipFile(jar_path, 'r') as zf:
            for name in zf.namelist():
                if name.upper() == 'META-INF/MANIFEST.MF':
                    data = zf.read(name).decode('utf-8', errors='ignore')
                    for line in data.splitlines():
                        if line.lower().startswith('implementation-version:'):
                            return line.split(':', 1)[1].strip()
    except Exception:
        return None
    return None


def find_version_in_filenames(root):
    patterns = [
        r'activemq-(?:broker|all|client)-(?P<v>\d+\.\d+\.\d+)\.jar$',
        r'apache-activemq-(?P<v>\d+\.\d+\.\d+)',
        r'activemq-(?P<v>\d+\.\d+\.\d+)'
    ]
    candidates = []
    for base, _, files in os.walk(root):
        for f in files:
            for pat in patterns:
                m = re.search(pat, f)
                if m:
                    candidates.append(m.group('v'))
    if candidates:
        # Prefer highest parsed version found in the tree
        parsed = [norm_version(c) for c in candidates]
        parsed = [p for p in parsed if p is not None]
        if parsed:
            parsed.sort()
            return version_to_str(parsed[-1])
    return None


def run_activemq_version(home):
    bin_candidates = [Path(home) / 'bin' / 'activemq', Path(home) / 'bin' / 'activemq.bat']
    for candidate in bin_candidates:
        if candidate.exists():
            try:
                if candidate.suffix.lower() == '.bat':
                    proc = subprocess.run([str(candidate)], capture_output=True, text=True, timeout=15, shell=True)
                else:
                    proc = subprocess.run([str(candidate), '--version'], capture_output=True, text=True, timeout=15)
                out = (proc.stdout or '') + '\n' + (proc.stderr or '')
                m = re.search(r'(\d+\.\d+\.\d+)', out)
                if m:
                    return m.group(1)
            except Exception:
                pass
    return None


def extract_version(target):
    p = Path(target)

    # Raw version string
    raw = norm_version(target)
    if raw:
        return version_to_str(raw), 'user-supplied version string'

    # Jar file
    if p.is_file() and p.suffix.lower() == '.jar':
        mv = read_manifest_version(str(p))
        if mv:
            return mv, f'manifest in {p.name}'
        m = re.search(r'(\d+\.\d+\.\d+)', p.name)
        if m:
            return m.group(1), f'filename {p.name}'
        return None, f'could not extract version from {p}'

    # Directory / install root
    if p.is_dir():
        v = run_activemq_version(str(p))
        if v:
            return v, f'{p}/bin/activemq'

        lib = p / 'lib'
        if lib.is_dir():
            for jar_name in ['activemq-broker', 'activemq-all', 'activemq-client']:
                jars = sorted(lib.glob(f'{jar_name}-*.jar'))
                for jar in jars:
                    mv = read_manifest_version(str(jar))
                    if mv:
                        return mv, f'manifest in {jar.name}'
                    m = re.search(r'(\d+\.\d+\.\d+)', jar.name)
                    if m:
                        return m.group(1), f'filename {jar.name}'

        fv = find_version_in_filenames(str(p))
        if fv:
            return fv, f'filenames under {p}'

        return None, f'could not determine version from {p}'

    return None, 'target path not found'


def main():
    if len(sys.argv) != 2:
        print('UNKNOWN - ' + USAGE)
        sys.exit(3)

    target = sys.argv[1]
    version_str, source = extract_version(target)
    vt = norm_version(version_str) if version_str else None

    if vt is None:
        print(f'UNKNOWN - Unable to determine ActiveMQ version ({source})')
        sys.exit(2)

    vuln = is_vulnerable(vt)
    if vuln is None:
        print(f'UNKNOWN - Parsed version {version_to_str(vt)} but could not classify')
        sys.exit(2)

    if vuln:
        print(f'VULNERABLE - ActiveMQ version {version_to_str(vt)} from {source} matches CVE-2026-41044 affected ranges (<5.19.6 or 6.0.0-6.2.4)')
        sys.exit(1)
    else:
        print(f'PATCHED - ActiveMQ version {version_to_str(vt)} from {source} is outside the CVE-2026-41044 affected ranges')
        sys.exit(0)


if __name__ == '__main__':
    main()
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, inventory every ActiveMQ Classic instance with the web console or Jolokia enabled and sort them by whether 8161 is reachable from anything beyond an admin enclave. For this MEDIUM reassessment there is no noisgate mitigation SLA — go straight to the 365-day remediation window; that means use exposure reduction as smart hygiene now, but finish the actual upgrade to 5.19.6 or 6.2.5+ within the noisgate remediation SLA, which from 2026-05-29 lands no later than 2027-05-29.

Sources

  1. Apache vendor advisory
  2. Apache ActiveMQ Classic security advisories
  3. NVD record
  4. ActiveMQ Classic REST and Jolokia documentation
  5. ActiveMQ Classic web console documentation
  6. ActiveMQ 6.2.5 release
  7. ActiveMQ 5.19.6 release
  8. CISA Known Exploited Vulnerabilities catalog
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.