Skip to content

CVE-2026-34486: Verified Repro With Script Download

CVE-2026-34486: Apache Tomcat EncryptInterceptor Bypass via CVE-2026-29146 Fix Error - Missing Encryption of Sensitive Data

CVE-2026-34486 is verified against the affected target. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00131.

REPRO-2026-00131 Apr 14, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
7.5
Reproduced in
19m 38s
Tool calls
176
01 · Overview

What Is CVE-2026-34486?

CVE-2026-34486 is a high-severity Missing Encryption of Sensitive Data vulnerability in Apache Tomcat's EncryptInterceptor (tomcat-tribes clustering subsystem) that lets an attacker bypass encryption entirely. Pruva reproduced it (reproduction REPRO-2026-00131).

02 · Severity & CVSS

CVE-2026-34486 Severity & CVSS Score

CVE-2026-34486 is rated high severity, with a CVSS base score of 7.5 out of 10.

HIGH threat level
7.5 / 10 CVSS base
Weakness CWE-311

High — serious impact or readily exploitable. Prioritize remediation.

How to Reproduce CVE-2026-34486

$ pruva-verify REPRO-2026-00131
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00131/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-34486

Reproduced by Pruva's autonomous agents — 176 tool calls over 20 min. Full root-cause analysis and the complete transcript are below.

How the agent worked 227 events · 176 tool calls · 20 min
20 minDuration
176Tool calls
47Reasoning steps
227Events
1Dead-ends
Agent activity over 20 min
Support
8
Repro
92
Judge
15
Variant
109
0:0019:38

Root Cause and Exploit Chain for CVE-2026-34486

Summary

CVE-2026-34486 is a Missing Encryption of Sensitive Data vulnerability in Apache Tomcat's EncryptInterceptor component within the tomcat-tribes clustering subsystem. The vulnerability allows an attacker to bypass encryption entirely by sending malformed or corrupted ciphertext that causes decryption to fail. Due to a code refactoring error introduced in the fix for CVE-2026-29146 (a padding oracle vulnerability), the super.messageReceived(msg) call was placed outside the try-catch block that handles decryption. As a result, when decryption throws a GeneralSecurityException (or any exception), the exception is caught and logged but the unprocessed (encrypted/corrupted) message is still forwarded downstream as if it were legitimate, effectively bypassing the encryption layer.

Impact

  • Package/Component affected: org.apache.catalina.tribes.group.interceptors.EncryptInterceptor (tomcat-tribes module)
  • Affected versions: Apache Tomcat 11.0.20, 10.1.53, 9.0.116
  • Risk level: HIGH (CVSS: 7.5)
  • CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
  • Consequences:
    • Encrypted cluster messages can be processed without proper decryption
    • Session replication data may be exposed or corrupted
    • Attackers with network access to Tomcat cluster can send arbitrary malformed messages that bypass encryption checks
    • Confidentiality impact: HIGH — sensitive session/cluster data may leak in plaintext or corrupted form

Root Cause

The vulnerability stems from a refactoring error in the patch for CVE-2026-29146. In the vulnerable versions, the EncryptInterceptor.messageReceived() method has the following flawed structure:

public void messageReceived(ChannelMessage msg) {
    try {
        // Decryption logic
        xbb.clear();
        xbb.append(data, 0, data.length);
    } catch (GeneralSecurityException gse) {
        log.error(sm.getString("encryptInterceptor.decrypt.failed"), gse);
    }
    super.messageReceived(msg);  // BUG: Outside try-catch — executes regardless of decryption failure!
}

The super.messageReceived(msg) call is outside the try-catch block, meaning it executes even when decryption fails and throws an exception. The correct behavior would be to only forward the message downstream if decryption succeeded, or to drop/abort processing on failure.

This is a classic exception handling bug: the catch block swallows the exception but doesn't prevent the downstream code path from executing.

Reproduction Steps

  1. Reference: repro/reproduction_steps.sh in this repository
  2. What the script does:
    • Downloads Apache Tomcat tomcat-tribes 11.0.20 JARs (vulnerable version)
    • Compiles a Java test class (TestEncryptInterceptorBypass.java) that:
      • Creates an EncryptInterceptor with a known encryption key
      • Chains a ValueCaptureInterceptor downstream to observe forwarded messages
      • Step 1: Sends a valid plaintext message and confirms normal encryption/decryption works (baseline)
      • Step 2: Sends malformed ciphertext (random bytes, wrong length) that triggers IllegalBlockSizeException during decryption
      • Asserts that the malformed ciphertext was forwarded downstream unchanged (bypass confirmed)
    • Runs the test and exits 0 on success, 1 on failure
  3. Expected evidence:
    • Log output showing "Failed to decrypt message" with IllegalBlockSizeException
    • Captured downstream bytes matching the input malformed ciphertext exactly
    • Final message: ">>> VULNERABILITY CONFIRMED <<<"

Evidence

  • Log output: logs/reproduction.log (generated by running repro/reproduction_steps.sh)
  • Key excerpts proving reproduction:
    Apr 14, 2026 12:41:17 PM org.apache.catalina.tribes.group.interceptors.EncryptInterceptor messageReceived
    SEVERE: Failed to decrypt message
    javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    ...
    Captured downstream:    000102030405060708090a0b0c0d0e0ffffefdfc4142434445464748
    >>> VULNERABILITY CONFIRMED <<<
    The malformed ciphertext was forwarded downstream UNCHANGED!
    Decrypt failed but super.messageReceived() was still called.
    CVE-2026-34486 is REPRODUCED.
    
  • Environment: Java 17 (OpenJDK), tomcat-tribes 11.0.20, tomcat-juli 11.0.20
  • Script exit code: 0 (confirmed)
  • Reproducibility: Verified twice consecutively with consistent results

Recommendations / Next Steps

  1. Immediate fix: Move super.messageReceived(msg) inside the try block so it only executes on successful decryption. If decryption fails, the method should return early or propagate the exception.

  2. Upgrade guidance: Upgrade to a patched version of Apache Tomcat once available. The fixed versions should ensure that super.messageReceived() is only called within the try block, or that an explicit return/throw follows exception handling.

  3. Testing recommendations:

    • Add unit tests that verify malformed ciphertext does NOT reach downstream interceptors
    • Test with various malformed inputs: wrong key, truncated ciphertext, invalid padding, wrong block size
    • Verify that legitimate encrypted messages still decrypt and forward correctly after the fix
    • Test the CVE-2026-29146 fix did not regress the padding oracle protection

Additional Notes

  • Idempotency: The reproduction script is fully idempotent — it uses a temporary directory and downloads dependencies fresh each run. Running it twice produces identical results.
  • Edge cases:
    • The bug manifests with any input that causes decryption to fail, including wrong key, wrong block size, invalid padding, or corrupted ciphertext.
    • The exception type observed was IllegalBlockSizeException (a subclass of GeneralSecurityException), but other GeneralSecurityException subclasses would trigger the same bypass.
    • The downstream interceptor receives the raw unprocessed bytes, not any form of decrypted output.
  • Limitations: This reproduction tests the library-level EncryptInterceptor via a Java harness. A full cluster-level test with running Tomcat instances would further demonstrate real-world impact but is not required to confirm the bug.

CVE-2026-34486 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:002:33
0:00
session startedgpt-4o · CVE-2026-34486 · 0332447d
0:04
web search
0:08
0:12
web search
0:16
web search
0:21
web search
0:26
0:32
extract_facts
no facts extracted
0:33
0:33
supportrepro
0:44
0:44
0:45
0:45
0:46
0:46
0:51
0:54
0:55
web search
1:01
1:03
1:06
1:08
web search
1:23
1:25
web search
1:28
1:28
$curl -sL "https://github.com/apache/tomcat/commit/1fab40ccc752e22639eccfe290d5624afad7eccd.patch" 2>/dev/null | head -200
0.4s
{"cwd":"/data/pruva/runs/0332447d-9fce-49c0-953d-e7a8666d57cb","duration_ms":382,"exit_code":0,"stderr":"","stdout":"From 1fab40ccc752e22639eccfe290d5624afad7eccd Mon Sep 17 00:00:00 2001\nFrom: Mark Thomas <markt@apache.org>\nDate: Mon, 30 Mar 2026 09:01:48 +0100\nSubject: [PATCH] Better error handling - partial revert of 6d955cc\n\n---\n .../catalina/tribes/group/interceptors/EncryptInterceptor.java | 2 +-\n webapps/docs/changelog.xml                                     | 3 +++\n 2 files changed, 4 insertions(+), 1 deletion(-)\n\ndiff --git a/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java b/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java\nindex 31866f254cd1..291f46724c8f 100644\n--- a/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java\n+++ b/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java\n@@ -140,10 +140,10 @@ public void messageReceived(ChannelMessage msg) {\n             xbb.clear();\n             xbb.append(data, 0, data.length);\n \n+            super.messageReceived(msg);\n         } catch (GeneralSecurityException gse) {\n             log.error(sm.getString(\"encryptIn… [truncated]
1:33
1:34
$curl -sL "https://github.com/apache/tomcat/commit/6d955cc.patch" 2>/dev/null | head -200
0.4s
{"cwd":"/data/pruva/runs/0332447d-9fce-49c0-953d-e7a8666d57cb","duration_ms":439,"exit_code":0,"stderr":"","stdout":"From 6d955cceca841f2eabf2d6c46b59a8c7e1cd6eaa Mon Sep 17 00:00:00 2001\nFrom: Mark Thomas <markt@apache.org>\nDate: Fri, 13 Mar 2026 13:18:39 +0000\nSubject: [PATCH] Add support for new algorithms provided by JPA providers\n\n---\n .../interceptors/EncryptInterceptor.java      |  64 +++++--\n .../interceptors/LocalStrings.properties      |   5 +-\n .../interceptors/LocalStrings_fr.properties   |   1 -\n .../interceptors/LocalStrings_ja.properties   |   1 -\n .../interceptors/LocalStrings_ko.properties   |   1 -\n .../LocalStrings_zh_CN.properties             |   1 -\n .../interceptors/TestEncryptInterceptor.java  |  58 -------\n .../TestEncryptInterceptorAlgorithms.java     | 162 ++++++++++++++++++\n webapps/docs/changelog.xml                    |   4 +\n webapps/docs/config/cluster-interceptor.xml   |  19 +-\n 10 files changed, 231 insertions(+), 85 deletions(-)\n create mode 100644 test/org/apache/catalina/tribes/group/interceptors/TestEncryptInterceptorAlgorithms.java\n\ndiff --git a/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java b/java… [truncated]
1:42
1:42
$curl -sL "https://raw.githubusercontent.com/apache/tomcat/refs/tags/11.0.20/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java" 2>/dev/null | head -180
0.3s
{"cwd":"/data/pruva/runs/0332447d-9fce-49c0-953d-e7a8666d57cb","duration_ms":267,"exit_code":0,"stderr":"","stdout":"/*\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements.  See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License.  You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.apache.catalina.tribes.group.interceptors;\n\nimport java.io.Serial;\nimport java.security.GeneralSecurityException;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.NoSuchProviderException;\nimport java.security.SecureRandom;\… [truncated]
1:51
1:51
$which mvn && mvn --version 2>/dev/null || echo "Maven not found"
Maven not found
2:10
2:10
$apt-get update -qq && apt-get install -y -qq maven openjdk-17-jdk-headless 2>&1 | tail -5
E: List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)
2:12
$whoami && which java && java -version 2>&1
vscode
2:27
$sudo apt-get update -qq 2>&1 | tail -3 && sudo apt-get install -y -qq maven openjdk-17-jdk-headless 2>&1 | tail -10
13.0s
{"cwd":"/data/pruva/runs/0332447d-9fce-49c0-953d-e7a8666d57cb","duration_ms":13018,"exit_code":0,"stderr":"","stdout":"update-alternatives: using /usr/lib/jvm/java-17-openjdk-arm64/bin/jmap to provide /usr/bin/jmap (jmap) in auto mode\r\nupdate-alternatives: using /usr/lib/jvm/java-17-openjdk-arm64/bin/jmod to provide /usr/bin/jmod (jmod) in auto mode\r\nupdate-alternatives: using /usr/lib/jvm/java-17-openjdk-arm64/bin/jps to provide /usr/bin/jps (jps) in auto mode\r\nupdate-alternatives: using /usr/lib/jvm/java-17-openjdk-arm64/bin/jrunscript to provide /usr/bin/jrunscript (jrunscript) in auto mode\r\nupdate-alternatives: using /usr/lib/jvm/java-17-openjdk-arm64/bin/jshell to provide /usr/bin/jshell (jshell) in auto mode\r\nupdate-alternatives: using /usr/lib/jvm/java-17-openjdk-arm64/bin/jstack to provide /usr/bin/jstack (jstack) in auto mode\r\nupdate-alternatives: using /usr/lib/jvm/java-17-openjdk-arm64/bin/jstat to provide /usr/bin/jstat (jstat) in auto mode\r\nupdate-alternatives: using /usr/lib/jvm/java-17-openjdk-arm64/bin/jstatd to provide /usr/bin/jstatd (jstatd) in auto mode\r\nupdate-alternatives: using /usr/lib/jvm/java-17-openjdk-arm64/bin/serialver to provide /usr/b… [truncated]
2:33
2:33
$which mvn && mvn --version 2>&1 | head -3
/usr/bin/mvn
Apache Maven 3.8.7
Maven home: /usr/share/maven
Java version: 21.0.10, vendor: Ubuntu, runtime: /usr/lib/jvm/java-21-openjdk-arm64

Artifacts and Evidence for CVE-2026-34486

Scripts, logs, diffs, and output captured during the reproduction.

No artifacts available

08 · How to Fix

How to Fix CVE-2026-34486

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-34486 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-34486

How does the CVE-2026-34486 encryption-bypass attack work?

An attacker with network access to the Tomcat cluster sends a malformed or corrupted ciphertext message to EncryptInterceptor. Decryption fails and throws an exception, but because messageReceived() was refactored to call super.messageReceived(msg) outside the catch block, the interceptor still forwards the message downstream unencrypted/unvalidated, bypassing the intended encryption layer for session replication and cluster data.

Which Apache Tomcat versions are affected by CVE-2026-34486?

Apache Tomcat 11.0.20, 10.1.53, and 9.0.116 are affected, per the record's root-cause analysis.

How severe is CVE-2026-34486?

It is rated high severity (CVSS 7.5 per the analysis, vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N): attackers with network access to the Tomcat cluster can send arbitrary malformed messages that bypass encryption checks, potentially exposing session replication data.

How can I reproduce CVE-2026-34486?

Download the verified script from this page and run it in an isolated environment against Apache Tomcat 11.0.20/10.1.53/9.0.116 with tomcat-tribes clustering enabled. It sends a malformed encrypted cluster message that triggers a decryption exception in EncryptInterceptor, then confirms the corrupted message is still processed downstream rather than dropped.
11 · References

References for CVE-2026-34486

Authoritative sources for CVE-2026-34486 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.