A one-line regression turned Tomcat's encryption guard into an open door — and attackers walked right through it
CVE-2026-34486 is a fail-open regression in Apache Tomcat's EncryptInterceptor, the component that encrypts Tribes cluster-to-cluster traffic. The fix for CVE-2026-29146 (a padding oracle) accidentally moved super.messageReceived(msg) outside the try-catch block in EncryptInterceptor.messageReceived(). When decryption of an inbound cluster message fails, the exception is caught and logged — but execution continues, forwarding the attacker's raw, unencrypted bytes straight into XByteBuffer.deserialize(), which calls bare ObjectInputStream.readObject() with no ObjectInputFilter. An attacker who can reach the Tribes NioReceiver (default TCP/4000) can send a crafted Java serialized object — typically a CommonsCollections6 gadget chain via ysoserial — and achieve unauthenticated remote code execution as the Tomcat process user. Exactly three point releases carry the regression: 9.0.116, 10.1.53, and 11.0.20. Fixed in 9.0.117, 10.1.54, and 11.0.21 (released April 2–4, 2026).
The vendor rated this Important / HIGH 7.5 with a CVSS vector of AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N — modeling only the *encryption bypass* (confidentiality loss) without accounting for the downstream deserialization-to-RCE chain. That is a material understatement. The actual exploitation outcome is full remote code execution with no authentication, no user interaction, and complete compromise of the host. CISA agreed: the KEV entry carries a 3-day remediation due date (August 7, 2026). The EPSS score of 0.985 places this in the top 1.5% of all CVEs for predicted exploitation probability, and Unit 42 has attributed active exploitation to the China-nexus actor knaithe (UNC5174/UNC6586), deploying SNOWLIGHT malware via an AI-driven scanning campaign. The vendor's 7.5 score dangerously undersells the real risk.
5 steps from start to impact.
Locate exposed Tribes receiver
NioReceiver port for Tomcat Tribes clustering). This port speaks a binary Tribes protocol and is trivially distinguishable from HTTP. In the knaithe campaign, automated scanning via the Hermes agent framework targeted 460+ hosts. Shodan/Censys dorks for this port are straightforward, though most Tribes ports are internal-facing.- Target runs Tomcat 9.0.116, 10.1.53, or 11.0.20
- Tribes clustering is enabled in
server.xml - TCP/4000 (or configured receiver port) is network-reachable from attacker
- Tribes clustering is not enabled by default — requires explicit
<Cluster>configuration - Port 4000 is rarely internet-facing; typically restricted to internal cluster VLAN
- Only 3 specific point versions carry the regression
ss -ltnp | grep :4000 on host inventory scansSend malformed Tribes frame with serialized payload
exp.py from 404-src/CVE-2026-34486) uses TribesClient.java to build a valid Tribes frame header and embeds a CommonsCollections6 gadget chain generated by ysoserial-all.jar. The 1496-byte frame is sent directly to the receiver port. No authentication, no TLS negotiation, no shared secret is required.- Network path to Tribes receiver port
- ysoserial or equivalent payload generator
- Knowledge of target's classpath gadgets (CC6 is a safe bet for most Tomcat deployments)
- Attacker must guess or enumerate available gadget libraries (though CommonsCollections is near-ubiquitous on Tomcat)
- Custom Tribes frame construction required (but PoC code handles this)
SEVERE...Failed to decrypt message...IllegalBlockSizeException: Input length must be multiple of 16 — this is the only indicator; the subsequent deserialization succeeds silentlyEncryptInterceptor fails open
EncryptInterceptor.messageReceived() method attempts to decrypt the incoming message. Because the attacker sent raw (unencrypted) bytes, decryption throws a GeneralSecurityException (typically AEADBadTagException or IllegalBlockSizeException). The catch block logs the error — but super.messageReceived(msg) sits outside the try block, so execution continues. The original attacker-controlled bytes in the message buffer are forwarded up the interceptor chain unchanged.- EncryptInterceptor is configured on the cluster channel (ironically, unpatched clusters *without* EncryptInterceptor were already vulnerable to direct deserialization via CVE-2025-24813)
- Only organizations that proactively configured EncryptInterceptor — typically security-conscious shops — carry this specific regression
- The bug was present for ~14 days in Maven Central before the fix shipped
Deserialization triggers gadget chain
XByteBuffer.deserialize(), which calls ObjectInputStream.readObject() with no ObjectInputFilter. The CommonsCollections6 chain (or any compatible gadget) executes its transformer chain, invoking Runtime.getRuntime().exec() or equivalent. The attacker achieves arbitrary command execution as the Tomcat process user — typically tomcat, root (in Docker), or a service account with access to application secrets, database credentials, and session stores.- A usable deserialization gadget library on the Tomcat classpath (CommonsCollections 3.x/4.x, Spring, Groovy, etc.)
- Tomcat ships with
commons-collectionsin many default webapp deployments; removing it breaks applications - Modern JDK serialization filters (
jdk.serialFilter) could block this if configured, but almost nobody sets them on Tomcat
ObjectInputStream.readObject() from network-sourced data; EDR alerting on child processes spawned by java with Tomcat classpathPost-exploitation: pivot across cluster
server.xml or referenced keystore), all replicated HTTP sessions, JDBC connection pool credentials, and network adjacency to every other cluster member. The knaithe campaign deployed SNOWLIGHT malware at this stage — a lightweight implant providing persistent backdoor access. From the compromised node, the attacker can replay the same exploit against sibling cluster nodes (they share the same vulnerable version and gadget libraries) or pivot to backend databases and internal services.- Successful RCE from step 4
- Network segmentation between Tomcat tier and backend databases may limit lateral movement
- Host-based EDR should detect SNOWLIGHT binary drop or suspicious
javachild processes
Receiver port) to only the IP addresses of legitimate cluster members via host firewall (iptables/nftables/Windows Firewall) or network security group. This breaks the attack path at step 1 by preventing attacker packets from reaching the vulnerable code. Deploy within the noisgate mitigation SLA of 3 days for CRITICAL severity. This is the single highest-ROI control if you cannot patch immediately.super.messageReceived(msg) back inside the try block, ensuring failed decryptions discard the message. Apply within the noisgate remediation SLA of 90 days — though given KEV status, aim for days not weeks. Verify the fix with the provided script.<Cluster> is configured in server.xml but session replication is not required (e.g., sticky sessions via load balancer suffice), remove or comment out the <Cluster> element and restart Tomcat. This eliminates the entire attack surface. Many Tomcat deployments have clustering configured from a template but never operationally use it.commons-collections-3.x.jar or upgrading to commons-collections4 with InvokerTransformer removed breaks the known exploit chains. However, this is fragile — other gadget libraries (Spring, Groovy, BeanUtils) may also be exploitable, and removing CC3 may break applications. Treat this as defense-in-depth, not a primary control.jdk.serialFilter in CATALINA_OPTS or jdk.serialFilter system property to reject dangerous classes (e.g., !org.apache.commons.collections.functors.*). This adds a defense layer at the JVM level against deserialization gadgets. Requires JDK 9+ or JDK 8u121+. Note: filter must be carefully tuned to avoid breaking legitimate Tribes deserialization.EncryptInterceptor log entries containing Failed to decrypt message, IllegalBlockSizeException, AEADBadTagException, or BadPaddingException. These are the only observable indicators of exploitation attempts — the subsequent deserialization and command execution produce no log output. Feed to SIEM with high-priority alerting. This is a detection control, not a prevention control.- WAF / reverse proxy in front of HTTP port — The attack targets the Tribes clustering port (TCP/4000), not the HTTP/HTTPS port (8080/8443). A WAF inspecting HTTP traffic will never see the malicious Tribes frames.
- TLS termination on the load balancer — TLS protects HTTP traffic to Tomcat, not internal Tribes cluster communication. The Tribes protocol has its own encryption layer (EncryptInterceptor), which is exactly what this CVE bypasses.
- Java Security Manager — Deprecated since JDK 17 and removed in JDK 24. Even where available, it was rarely configured restrictively enough to block
Runtime.exec()from deserialization contexts. Do not rely on it. - Upgrading to the initially-fixed versions (9.0.116, 10.1.53, 11.0.20) — These ARE the vulnerable versions. Organizations that patched for CVE-2026-29146 by upgrading to these releases inadvertently introduced CVE-2026-34486. You must go one version further.
The supporting signals.
| In-the-wild status | Actively exploited. CISA added CVE-2026-34486 to the KEV catalog on 2026-08-04 with a 3-day due date (2026-08-07). Palo Alto Unit 42 attributes exploitation to knaithe (UNC5174/UNC6586), a China-nexus actor using an AI-driven campaign via the DeepSeek model and Hermes agent framework, targeting 460+ hosts. SOCRadar reports a Taiwan-focused campaign deploying SNOWLIGHT malware via CommonsCollections6 deserialization. |
|---|---|
| Proof-of-concept | Multiple weaponized PoCs public. striga-ai/CVE-2026-34486 — Docker-based reproduction with CC6 payload. 404-src/CVE-2026-34486 — exp.py script using ysoserial CC6 chain, TribesClient.java for frame construction. Both include full exploit chains from payload generation to command execution validation. karczewski.io published a video PoC walkthrough. |
| EPSS | 0.98503 — top 1.5% of all scored CVEs. This places CVE-2026-34486 in the highest exploitation-probability tier, consistent with its KEV listing and weaponized PoC availability. |
| KEV status | Listed. Added 2026-08-04, due date 2026-08-07 (3-day window). Required action: apply vendor mitigations per BOD 26-04. Not flagged for ransomware use. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N (vendor, 7.5). This vector models only the encryption bypass / confidentiality loss. It does not capture the downstream deserialization-to-RCE chain (which would add I:H/A:H). A more accurate RCE-inclusive vector with clustering prerequisites: AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H = 8.1, or AC:L for deployments where clustering is already exposed = 9.8. |
| Affected versions | Exactly three point releases: Apache Tomcat 9.0.116, 10.1.53, 11.0.20. These were the latest releases when the regression shipped. Earlier versions are NOT affected by this specific CVE (though they may carry CVE-2026-29146 or other cluster deserialization issues). Tomcat 8.5.x is unaffected. |
| Fixed versions | 9.0.117 (2026-04-03), 10.1.54 (2026-04-02), 11.0.21 (2026-04-04). Distro backports: RHEL/CentOS — see Red Hat advisory; SUSE — SUSE KB. |
| Scanning/exposure | Tribes receiver port (TCP/4000) is typically internal-facing and not indexed by Shodan/Censys at scale. No public internet-wide scan statistics available. The knaithe campaign used automated recon against internal networks and cloud VPCs rather than internet-wide scanning. Individual sightings reported (e.g., exposed directory on 150.40.117[.]90:8000 with Tribes indicators). |
| Disclosure timeline | 2026-02-22: CVE-2026-29146 reported → 2026-03-26: CVE-2026-34486 regression reported → 2026-04-02–04: Fixes released → 2026-04-09: Public disclosure → 2026-08-04: CISA KEV addition |
| Reporting / attribution | Original vulnerability reported to Apache. Exploitation attributed by Palo Alto Unit 42 to knaithe (UNC5174/UNC6586). Campaign used DeepSeek AI model through Hermes agent framework for automated scanning and exploitation. |
Sources.
- Apache Tomcat 11 Security Advisories (vendor)
- CISA KEV Alert — CVE-2026-34486 Added
- 404-src/CVE-2026-34486 — Weaponized PoC (exp.py + ysoserial)
- striga-ai/CVE-2026-34486 — Docker reproduction lab
- Corgea Research — Root cause analysis with KEV context
- johal.in — One-line diff deep dive
- SOCRadar — SNOWLIGHT campaign attribution
- Red Hat Security Advisory
Why this verdict
- Vendor underscore is structurally wrong. The vendor CVSS (7.5) models *only* the encryption bypass (C:H/I:N/A:N). The documented, reproducible, and actively exploited chain ends in unauthenticated remote code execution — the correct impact tuple is C:H/I:H/A:H. This alone would push the base score to 9.8 if attack complexity were Low.
- KEV-listed with the shortest possible CISA deadline. Added 2026-08-04 with a 3-day remediation due date (2026-08-07), confirming CISA's assessment that this is an actively exploited, high-impact vulnerability requiring emergency response.
- EPSS 0.985 confirms weaponization. An EPSS score in the top 1.5% is not a theoretical risk — it reflects observed exploitation patterns, public PoC maturity, and attacker adoption rates consistent with the multiple weaponized exploit repositories.
- APT-grade exploitation in active campaigns. Unit 42's attribution to knaithe (UNC5174/UNC6586) with AI-driven scanning and SNOWLIGHT malware deployment demonstrates this is not opportunistic scanning — it is targeted, persistent, and operationally mature.
- Clustering prerequisite narrows population but not severity. Tribes clustering is not default-enabled, and port 4000 is typically internal. However, where clustering IS enabled, it is invariably in production high-availability environments handling sensitive session data and backend credentials — exactly the environments where RCE matters most.
- Role multiplier: Apache Tomcat is the dominant Java application server. When Tribes clustering is configured, the deployment is by definition a production HA tier — category (b) at minimum. In many enterprises, Tomcat cluster nodes serve as the application layer for ERP, CRM, healthcare, and financial applications. Compromise of one node yields: (1) all replicated sessions across the cluster, (2) JDBC credentials for backend databases, (3) the shared EncryptInterceptor key enabling exploitation of every sibling node. This is application-tier-scale blast radius. In organizations running Jenkins on Tomcat (common legacy pattern), this becomes CI/CD-scale — a supply-chain pivot. The production-HA deployment pattern means ≥80% of affected installs (those running clustering) occupy category (b) or higher roles.
- Gadget availability is near-universal. CommonsCollections 3.x ships with or alongside most Tomcat webapp deployments. The CC6 chain used in public PoCs works out-of-the-box against the vast majority of real Tomcat classpaths.
Why not higher?
A 10.0 would require zero prerequisites and universal exposure. This vulnerability requires Tribes clustering to be explicitly enabled (not default), port 4000 to be network-reachable, and a deserialization gadget library on the classpath. While all three conditions are commonly met in production clustering deployments, they do meaningfully narrow the vulnerable population to a subset of all Tomcat installations — perhaps 5–15% of the installed base.
Why not lower?
Downgrading below CRITICAL would require dismissing the confirmed active exploitation by a nation-state-attributed APT, the KEV listing with a 3-day deadline, the EPSS score of 0.985, and the demonstrated RCE outcome. The clustering prerequisite is a population limiter, not a complexity barrier — where clustering is enabled, exploitation is trivial (send one packet, get shell). The vendor's 7.5 HIGH rating is based on an incomplete impact model that ignores the deserialization chain entirely.
Crowdsourced verification payload.
Run this script on each Tomcat host as any user with read access to the Tomcat installation directory. Invoke: bash check_cve_2026_34486.sh /opt/tomcat (pass your CATALINA_HOME as the first argument). No root required unless server.xml is root-readable only.
#!/usr/bin/env bash
# check_cve_2026_34486.sh — Detect CVE-2026-34486 exposure
# Usage: bash check_cve_2026_34486.sh /path/to/catalina_home
# Exit codes: 1=VULNERABLE, 0=PATCHED, 2=UNKNOWN
set -euo pipefail
CATALINA_HOME="${1:-}"
if [ -z "$CATALINA_HOME" ]; then
echo "Usage: $0 <CATALINA_HOME>"
exit 2
fi
# --- Determine Tomcat version ---
VERSION_FILE="$CATALINA_HOME/lib/catalina.jar"
if [ ! -f "$VERSION_FILE" ]; then
echo "[UNKNOWN] Cannot find catalina.jar at $CATALINA_HOME/lib/"
exit 2
fi
VERSION=$(unzip -p "$VERSION_FILE" org/apache/catalina/util/ServerInfo.properties 2>/dev/null \
| grep '^server.number=' | cut -d= -f2 | tr -d '[:space:]')
if [ -z "$VERSION" ]; then
echo "[UNKNOWN] Could not extract Tomcat version from catalina.jar"
exit 2
fi
echo "[INFO] Detected Tomcat version: $VERSION"
# --- Check if version is one of the three affected releases ---
VULN_VERSIONS="9.0.116 10.1.53 11.0.20"
IS_VULN_VERSION=false
for v in $VULN_VERSIONS; do
if [ "$VERSION" = "$v" ]; then
IS_VULN_VERSION=true
break
fi
done
if [ "$IS_VULN_VERSION" = false ]; then
echo "[PATCHED] Tomcat $VERSION is not one of the affected versions (9.0.116, 10.1.53, 11.0.20)."
exit 0
fi
echo "[WARNING] Tomcat $VERSION is an affected version."
# --- Check if Tribes clustering is enabled ---
SERVER_XML="$CATALINA_HOME/conf/server.xml"
if [ ! -f "$SERVER_XML" ]; then
echo "[UNKNOWN] Cannot find server.xml at $SERVER_XML"
exit 2
fi
CLUSTER_ENABLED=false
if grep -qiE '<Cluster\b|SimpleTcpCluster|DeltaManager|BackupManager' "$SERVER_XML" 2>/dev/null; then
# Check it's not commented out
if grep -E '<Cluster\b|SimpleTcpCluster' "$SERVER_XML" | grep -qvE '^\s*<!--'; then
CLUSTER_ENABLED=true
fi
fi
if [ "$CLUSTER_ENABLED" = false ]; then
echo "[PATCHED] Tomcat $VERSION detected but Tribes clustering is NOT enabled in server.xml."
echo "[INFO] The EncryptInterceptor bypass is not reachable without clustering. Low risk."
exit 0
fi
echo "[WARNING] Tribes clustering IS enabled."
# --- Check if EncryptInterceptor is configured ---
ENCRYPT_CONFIGURED=false
if grep -qiE 'EncryptInterceptor' "$SERVER_XML" 2>/dev/null; then
if grep -E 'EncryptInterceptor' "$SERVER_XML" | grep -qvE '^\s*<!--'; then
ENCRYPT_CONFIGURED=true
fi
fi
if [ "$ENCRYPT_CONFIGURED" = true ]; then
echo "[WARNING] EncryptInterceptor IS configured — fail-open bypass is active."
else
echo "[WARNING] EncryptInterceptor is NOT configured — cluster traffic is unencrypted."
echo "[INFO] CVE-2026-34486 specifically requires EncryptInterceptor, but unencrypted"
echo " clustering is arguably worse (direct deserialization with no encryption at all)."
fi
# --- Check if receiver port is listening ---
RECEIVER_PORT=4000
CUSTOM_PORT=$(grep -oP 'Receiver[^>]*port="\K[0-9]+' "$SERVER_XML" 2>/dev/null | head -1)
if [ -n "$CUSTOM_PORT" ]; then
RECEIVER_PORT=$CUSTOM_PORT
fi
PORT_OPEN=false
if command -v ss &>/dev/null; then
if ss -ltnp 2>/dev/null | grep -q ":${RECEIVER_PORT} "; then
PORT_OPEN=true
fi
elif command -v netstat &>/dev/null; then
if netstat -tlnp 2>/dev/null | grep -q ":${RECEIVER_PORT} "; then
PORT_OPEN=true
fi
fi
if [ "$PORT_OPEN" = true ]; then
echo "[WARNING] Tribes receiver port $RECEIVER_PORT is LISTENING."
else
echo "[INFO] Tribes receiver port $RECEIVER_PORT does not appear to be listening (Tomcat may not be running)."
fi
# --- Final verdict ---
echo ""
echo "=== RESULT ==="
if [ "$CLUSTER_ENABLED" = true ]; then
echo "[VULNERABLE] Tomcat $VERSION with Tribes clustering enabled."
echo " Action: Upgrade immediately to 9.0.117 / 10.1.54 / 11.0.21+"
echo " Interim: Firewall port $RECEIVER_PORT to cluster members only."
exit 1
else
echo "[PATCHED] Vulnerable version detected but clustering not enabled. Not exploitable."
exit 0
fi