Someone left a trick envelope in the mailroom that makes the sorter read two letters where there's only one
CVE-2023-46589 is an HTTP request smuggling vulnerability in Apache Tomcat caused by incorrect parsing of HTTP trailer headers. When a trailer header exceeds the configured maxTrailerSize, Tomcat fails to reject the request cleanly and instead treats a single inbound request as multiple separate requests. This desync between the front-end reverse proxy's view and Tomcat's view of request boundaries is the textbook setup for request smuggling. Affected versions span Tomcat 9.0.0-M1 through 9.0.82 (also 8.5.0–8.5.95, 10.1.0-M1–10.1.15, 11.0.0-M1–11.0.0-M10). Fixed in 9.0.83.
The vendor (Apache) rated this Important and NVD assigned CVSS 7.5 HIGH with the vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N. That score reflects the theoretical network-reachable, no-auth, integrity-only impact — and it's technically correct on paper. However, it overstates the practical risk today. Nearly three years post-disclosure there is no public proof-of-concept, no known in-the-wild exploitation, EPSS sits at ~2.6% (well below the 90th percentile), and the vulnerability is not in the CISA KEV catalog. The impact ceiling is integrity manipulation (cache poisoning, request routing abuse) rather than direct code execution. Tenable's own VPR of 3.0 agrees this is low real-world risk. noisgate downgrades to MEDIUM.
4 steps from start to impact.
Identify Tomcat behind a reverse proxy
- Target runs Tomcat 9.0.0-M1 – 9.0.82 (or equivalent affected branch)
- Tomcat sits behind a reverse proxy that forwards chunked/TE requests
- If Tomcat is accessed directly (no proxy), the smuggling desync has no front-end to exploit
- Some proxies normalize or strip trailer headers before forwarding, neutralizing the attack
Craft oversized trailer header request
maxTrailerSize (default 8192 bytes). The key is that the trailer content must be carefully sized to trigger the parser bug where Tomcat interprets the tail of the first request as the beginning of a second request.- Ability to send raw HTTP requests to the proxy front-end
- Chunked transfer encoding must be forwarded to Tomcat (not decoded by proxy)
- No public PoC exists — the attacker must develop the exploit from scratch using only the patch diff (commit
7a2d881) - WAFs with request smuggling detection rules (e.g., AWS ALB, Cloudflare, ModSecurity CRS rule 921110) may block malformed trailers
- Many modern proxies (e.g., nginx by default) do not forward trailer headers to backends
Smuggle a second request into Tomcat's pipeline
- Successful desync between proxy and Tomcat request boundary parsing
- A subsequent legitimate request must follow on the same keep-alive connection
- HTTP/2 front-ends that multiplex rather than pipeline largely neutralize this class of attack
- Connection pooling behavior varies — the smuggled request may land on the attacker's own connection, not a victim's
- Impact is bounded to integrity (I:H) — no direct path to code execution or confidentiality breach without chaining
Exploit smuggled request for cache poisoning or auth bypass
- Caching layer present (for cache poisoning) or auth-gating proxy (for auth bypass)
- Application must have sensitive endpoints reachable once the proxy gate is bypassed
- Modern architectures increasingly use per-request auth tokens validated at the backend, reducing the value of proxy-level auth bypass
- Cache poisoning requires predictable cache keys and shared caching infrastructure
- No documented real-world exploitation chain exists for this specific CVE
The supporting signals.
| In-the-Wild Exploitation | None observed. No known campaigns, no threat actor attribution, no mentions in threat intelligence feeds as of September 2026. |
|---|---|
| CISA KEV Status | Not listed. CVE-2023-46589 has not been added to the CISA Known Exploited Vulnerabilities catalog. |
| Proof-of-Concept | No public PoC. No exploit code on GitHub, ExploitDB, or from named researchers. The patch diff (commit 7a2d881) is the only public technical reference. |
| EPSS Score | 0.0265 (2.65%) — low probability of exploitation in the next 30 days. Well below the threshold that typically drives urgency. |
| CVSS 3.1 Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N — network-reachable, no auth required, no user interaction, integrity-only impact. No confidentiality or availability impact. |
| Tenable VPR | 3.0 (Low) — Tenable's own risk-based score dramatically downgrades this from the CVSS 7.5 HIGH, reflecting the absence of real-world exploitation. |
| Affected Versions | Tomcat 9.0.0-M1 – 9.0.82, also 8.5.0–8.5.95, 10.1.0-M1–10.1.15, 11.0.0-M1–11.0.0-M10 |
| Fixed Versions | 9.0.83, 8.5.96, 10.1.16, 11.0.0-M11. RHEL backports: tomcat-9.0.87 (RHEL 9), Debian: 9.0.83-1. Ubuntu: check libservlet3.1-java package version. |
| Exposure Data | Shodan indexes ~3.4M Tomcat-responding hosts globally, but the vast majority sit behind reverse proxies and are not directly fingerprinted. Tomcat version granularity via Shodan is unreliable due to header suppression. |
| Disclosure Timeline | Reported to Apache: 2023-10-20. Public disclosure: 2023-11-28. Fix available same day. Now ~2 years 10 months old. |
noisgate verdict.
The single most decisive factor is the complete absence of proof-of-concept code or in-the-wild exploitation nearly three years post-disclosure, corroborated by an EPSS of 2.65% and Tenable's own VPR of 3.0. The integrity-only impact ceiling (no RCE, no confidentiality breach) without a documented chain to domain or fleet compromise keeps this firmly in the MEDIUM bucket.
Why this verdict
- No weaponization signal: Nearly 3 years post-disclosure with zero public PoC, zero KEV listing, zero named campaigns. EPSS at 2.65% confirms the security research community has not prioritized this.
- Integrity-only impact ceiling: The CVSS vector explicitly scores C:N/I:H/A:N. Request smuggling at this layer can enable cache poisoning or auth bypass, but there is no direct path to code execution, data exfiltration, or availability disruption without significant application-specific chaining.
- Proxy behavior as natural friction: While most enterprise Tomcat deployments *do* sit behind a reverse proxy (meeting the prerequisite), many modern proxies (nginx default config, HTTP/2 front-ends, AWS ALB) either strip trailer headers, decode chunked encoding, or use multiplexing — all of which neutralize this specific attack vector without any deliberate mitigation.
- Role multiplier: Tomcat is a general-purpose application server. In its *typical role* (line-of-business app tier), successful smuggling yields session hijacking or cache poisoning scoped to that application — tenant-level blast radius, not fleet or domain. In *high-value roles* (hosting an identity provider UI, admin console), the chain could theoretically escalate to auth bypass on sensitive endpoints, but (a) this requires the specific proxy+Tomcat+caching topology, (b) the integrity-only impact still does not yield RCE or credential extraction directly, and (c) no one has demonstrated this chain. The floor for HIGH is not met because the blast radius does not reach domain/fleet/supply-chain scale even in the worst plausible role.
- VPR corroboration: Tenable's own Vulnerability Priority Rating of 3.0 (Low) represents their machine-learning-driven assessment that real-world risk is minimal. When even the vendor's scanner says 'Low,' the CVSS 7.5 label is misleading.
Why not higher?
To warrant HIGH, we would need either active exploitation evidence, a public PoC demonstrating practical impact, or a blast radius that reaches domain/fleet scale. None of these conditions are met. The integrity-only CVSS vector with no confidentiality or availability component, combined with the natural friction of modern proxy architectures neutralizing trailer-based smuggling, means the theoretical 7.5 does not translate to HIGH real-world risk.
Why not lower?
Request smuggling is a non-trivial vulnerability class that has historically enabled serious attacks (see CVE-2023-25690, CVE-2023-46747 on F5). The network-reachable, no-auth attack surface is real, and Tomcat's massive installed base means even a small percentage of vulnerable+exploitable deployments is a large absolute number. Dropping to LOW would understate the risk for the subset of environments running vulnerable Tomcat behind proxies that do forward trailer headers.
What to do — in priority order.
- Configure reverse proxy to strip or reject HTTP trailer headers — In nginx, trailer headers are not forwarded by default. In Apache httpd, use
RequestHeader unset Traileror upgrade to a version that normalizes trailers. In HAProxy, setoption http-restrict-req-hdr-names reject. This eliminates the desync vector entirely. No noisgate mitigation SLA applies at MEDIUM — proceed directly to the 365-day remediation window. - Reduce Tomcat maxTrailerSize to 0 — Set
maxTrailerSize="0"in the Connector element ofserver.xmlto reject all trailer headers. This is a server-side hardening that blocks the specific parser bug regardless of proxy behavior. Test with your application first — very few applications legitimately use HTTP trailers. - Deploy WAF rules for HTTP request smuggling — Enable ModSecurity CRS rules 921110–921160 or equivalent on your WAF/ALB. AWS ALB and Cloudflare have built-in desync protection. This provides defense-in-depth even if trailer headers reach Tomcat.
- Upgrade Tomcat to 9.0.83+ — The definitive fix. The patch is a single commit and has been stable for nearly 3 years. Apply within the noisgate 365-day remediation window for MEDIUM severity.
- Network segmentation alone — the attack traverses the legitimate HTTP path through the reverse proxy; firewall rules that allow normal web traffic also allow the smuggling payload.
- TLS/mTLS between proxy and Tomcat — encryption protects the transport, not the application-layer parsing. The smuggled request rides inside a valid TLS session.
- Rate limiting — request smuggling requires only a single crafted request, not volume. Rate limits will not detect or prevent it.
Crowdsourced verification payload.
Run this on each Tomcat host (Linux/macOS) as any user with read access to the Tomcat install directory. Example: bash check_cve_2023_46589.sh /opt/tomcat. No root required.
#!/usr/bin/env bash
# check_cve_2023_46589.sh — Detect CVE-2023-46589 in Apache Tomcat 9.x
# Usage: bash check_cve_2023_46589.sh /path/to/tomcat
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
TOMCAT_HOME="${1:-}"
if [[ -z "$TOMCAT_HOME" ]]; then
echo "Usage: $0 /path/to/tomcat"
exit 2
fi
# Try version.sh first
if [[ -x "$TOMCAT_HOME/bin/version.sh" ]]; then
VERSION=$( "$TOMCAT_HOME/bin/version.sh" 2>/dev/null | grep -oP 'Server number:\s+\K[0-9.]+' || true )
elif [[ -f "$TOMCAT_HOME/lib/catalina.jar" ]]; then
VERSION=$( unzip -p "$TOMCAT_HOME/lib/catalina.jar" org/apache/catalina/util/ServerInfo.properties 2>/dev/null | grep -oP 'server.number=\K[0-9.]+' || true )
else
echo "UNKNOWN — Cannot determine Tomcat version at $TOMCAT_HOME"
exit 2
fi
if [[ -z "$VERSION" ]]; then
echo "UNKNOWN — Could not parse Tomcat version"
exit 2
fi
echo "Detected Tomcat version: $VERSION"
# Parse major.minor.patch
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
# Check if version is in affected 9.x range (9.0.0 - 9.0.82)
if [[ "$MAJOR" -eq 9 && "$MINOR" -eq 0 ]]; then
if [[ "$PATCH" -le 82 ]]; then
echo "VULNERABLE — Tomcat $VERSION is affected by CVE-2023-46589 (fixed in 9.0.83)"
exit 1
else
echo "PATCHED — Tomcat $VERSION is >= 9.0.83"
exit 0
fi
# Check 8.5.x range (8.5.0 - 8.5.95)
elif [[ "$MAJOR" -eq 8 && "$MINOR" -eq 5 ]]; then
if [[ "$PATCH" -le 95 ]]; then
echo "VULNERABLE — Tomcat $VERSION is affected by CVE-2023-46589 (fixed in 8.5.96)"
exit 1
else
echo "PATCHED — Tomcat $VERSION is >= 8.5.96"
exit 0
fi
# Check 10.1.x range
elif [[ "$MAJOR" -eq 10 && "$MINOR" -eq 1 ]]; then
if [[ "$PATCH" -le 15 ]]; then
echo "VULNERABLE — Tomcat $VERSION is affected by CVE-2023-46589 (fixed in 10.1.16)"
exit 1
else
echo "PATCHED — Tomcat $VERSION is >= 10.1.16"
exit 0
fi
else
echo "UNKNOWN — Tomcat $VERSION is outside the checked branch ranges (8.5.x, 9.0.x, 10.1.x)"
exit 2
fiIf you remember one thing.
maxTrailerSize="0" in server.xml and confirm your reverse proxy strips trailer headers — both are zero-risk changes for virtually all applications. Do not let this CVE bump ahead of actively exploited issues in your patch queue. The vendor CVSS of 7.5 and Tenable's HIGH label are theoretically sound but operationally misleading given zero PoC availability, zero exploitation evidence, and an EPSS of 2.65% after nearly three years.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.