Tenable stapled a 9.1 CRITICAL to a configuration quirk that Apache themselves shrugged off as LOW
This Tenable plugin (326730) bundles two CVEs fixed in Apache Tomcat 9.0.120. CVE-2026-59083 is the headliner: Tomcat's RewriteValve incorrectly decoded the + character in rewritten URIs as a space (via Java's URLDecoder.decode() instead of Tomcat's own UDecoder.URLDecode()). This mismatch between the rewrite engine and the security-constraint evaluator means a crafted URI containing + could slip past path-based access controls — but *only* when RewriteValve is explicitly configured AND the security constraints depend on URI integrity post-rewrite. Affected range: 9.0.0.M1 through 9.0.119 (also 10.1.x through 10.1.56 and 11.0.x through 11.0.23). CVE-2026-59084 is a documentation gap: the EncryptInterceptor (a Tomcat clustering component) didn't clearly state that AES/GCM/NoPadding is the only non-malleable cipher choice. Affected range for that one: 9.0.13 through 9.0.119.
The vendor severity is wildly inflated. Apache — the people who wrote Tomcat — rated both CVEs as Low. NVD assigned CVE-2026-59083 a CVSS 9.1 Critical vector (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N), which models an unauthenticated, zero-click, high-impact network attack. That vector ignores the most important real-world constraint: RewriteValve is not enabled by default. It's an optional component that most Tomcat operators never touch because URL rewriting is typically handled by a reverse proxy (nginx, Apache httpd, HAProxy). Tenable's VPR score of 4.3 (Medium) — their own risk-adjusted metric — already acknowledges this, yet the plugin headline still screams Critical. The 9.1 is mechanical CVSS math disconnected from operational reality.
3 steps from start to impact.
Identify Tomcat with RewriteValve enabled
RewriteValve in server.xml at the Host or Context level, or via a rewrite.config file in a webapp's WEB-INF directory. This component is not part of Tomcat's default configuration. Without it, the entire chain is dead on arrival.- Target runs Apache Tomcat 9.0.0.M1–9.0.119 (or equivalent 10.1.x/11.0.x range)
- RewriteValve is explicitly configured and active
- RewriteValve is not enabled by default — most enterprises use a reverse proxy for URL rewriting
- No reliable remote fingerprint to detect RewriteValve presence from the outside
- Shodan/Censys cannot distinguish RewriteValve-enabled instances from vanilla Tomcat
Map security constraints tied to rewritten paths
<security-constraint> declarations in web.xml whose enforcement depends on the URI remaining unchanged after the RewriteValve rewrites it. This requires trial-and-error probing of application-specific path patterns — there is no universal exploit URI.- Security constraints exist that gate access based on URI path
- Those constraints interact with RewriteValve rewrite rules in a way that URI mutation matters
- Configuration-dependent — varies per application, no generic payload
- Application-layer authorization (Spring Security, Shiro, custom filters) often duplicates constraint enforcement, making the bypass moot
- 403/401 responses from failed probes are noisy and logged
+-laden URIs. Application access logs will show unexpected path resolution.Craft +‑encoded URI to bypass constraint
+ characters in the path segment that the RewriteValve rewrites. The valve decodes + as a space, producing a rewritten URI that no longer matches the security constraint pattern. Tomcat then serves the protected resource. For example, a path like /admin/a+b/config might rewrite to /admin/a b/config, which does not match a constraint anchored on /admin/a+b/.- Network access to the Tomcat HTTP/HTTPS port
- No upstream reverse proxy normalizing
+before it reaches Tomcat
- Most production Tomcat sits behind a reverse proxy that may normalize or reject malformed path segments
- Application-level authZ checks (session validation, role checks in code) are unaffected by this bypass
- The attacker gains access only to what the bypassed constraint protected — often a single path prefix, not the whole application
The supporting signals.
| In-the-wild exploitation | Not confirmed. Not in CISA KEV. IONIX mentions "tracking ongoing exploitation attempts" but provides no corroborating evidence; likely refers to opportunistic scanning. No GreyNoise tags for either CVE as of 2026-09-21. |
|---|---|
| Proof-of-concept | None public. No exploit code on GitHub, ExploitDB, or Packet Storm. The only published demonstration is a local Java snippet showing URLDecoder.decode() vs UDecoder.URLDecode() output divergence — not a weaponized PoC. |
| EPSS | 0.0037 (~3rd percentile) for CVE-2026-59083. Extremely low predicted exploitation probability within 30 days. |
| CISA KEV | Not listed as of 2026-09-21. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N (9.1 Critical) — NVD-assigned. Apache vendor rating: Low. The vector assumes zero attack complexity, but exploitation requires RewriteValve configuration + specific constraint patterns, which CVSS does not model. |
| Affected versions | CVE-2026-59083: 9.0.0.M1–9.0.119 (also 10.1.0-M1–10.1.56, 11.0.0-M1–11.0.23, 8.5.0–8.5.100). CVE-2026-59084: 9.0.13–9.0.119 (also 10.1.0-M1–10.1.56, 11.0.0-M1–11.0.23, 8.5.38–8.5.100, 7.0.100–7.0.109). |
| Fixed versions | 9.0.120 (9.x branch), 10.1.57 (10.1.x), 11.0.24 (11.0.x). 8.5.x is EOL — no fix; migrate to a supported branch. Distro backports: check RHSA-2026:68659 (RHEL), DSA/DLA for Debian. |
| Exposure (Shodan) | ~100,000 internet-facing Tomcat instances indexed by Shodan globally. This count does not indicate RewriteValve usage — the vast majority run default configurations. |
| Disclosure timeline | Reported: 2026-06-26 (CVE-2026-59083), 2026-06-29 (CVE-2026-59084). Fixed in 9.0.120: 2026-07-07. Public disclosure: 2026-07-14. Tenable plugin published: 2026-07-14. |
| Reporter | Mark Thomas (Apache Tomcat PMC member) — disclosed via oss-security mailing list. |
Why this verdict
- RewriteValve is off by default — this is NOT a vulnerability in core Tomcat request processing. The
RewriteValvemust be explicitly added toserver.xmlor a webapp's context. Most enterprises delegate URL rewriting to a reverse proxy (nginx, Apache httpd), making the entire chain unreachable. Estimated <5–10% of Tomcat deployments enable RewriteValve at all. - Configuration-dependent bypass, not universal auth bypass — even among RewriteValve users, exploitation requires security constraints that gate access based on URI patterns that are mutated by the
+→space decoding. There is no generic exploit URI; each target requires custom analysis of rewrite rules and constraint mappings. - Apache rates both CVEs LOW — the vendor who wrote and maintains Tomcat assessed the real-world exploitability and chose their lowest severity tier. The NVD 9.1 CRITICAL treats the theoretical worst case (unauthenticated network attack, high C+I impact) without modeling the prerequisite configuration.
- No PoC, no KEV, EPSS 0.0037 — zero public exploit code, no confirmed exploitation in the wild, and FIRST's model predicts near-zero exploitation probability. Tenable's own VPR (4.3 Medium) already self-corrects away from the 9.1 headline.
- CVE-2026-59084 is a documentation issue — the second CVE in this bundle is about unclear docs for
EncryptInterceptorcipher selection. The EncryptInterceptor is part of Tomcat clustering (Tribes), a feature used by a tiny fraction of deployments. This is not an exploitable code vulnerability. - Role multiplier: Tomcat occupies the *typical role* of application-tier server. In high-value-role scenarios (e.g., Tomcat hosting an IdP like Keycloak, or a CI/CD frontend like Jenkins), the chain still requires RewriteValve + specific constraint configuration — it does not succeed by default. The blast radius when it does succeed is *host-level* access to a restricted path prefix, not domain/fleet/supply-chain impact. Because the prerequisite (RewriteValve with security-constraint dependency) affects well under 1% of the Tomcat installed base in high-value roles, no severity floor is triggered.
Why not higher?
The theoretical CVSS vector models an unauthenticated network attack with high confidentiality and integrity impact — but that vector ignores the mandatory RewriteValve prerequisite and the configuration-specific nature of the bypass. With no public PoC, no confirmed exploitation, EPSS at the 3rd percentile, and the vendor rating both CVEs LOW, there is no evidence-based justification for MEDIUM or above. The Tenable VPR of 4.3 already reflects this reality.
Why not lower?
Tomcat is ubiquitous enough that *some* deployments will have RewriteValve configured with security constraints, and for those specific instances the bypass is a real (if narrow) security control failure. The fix is a straightforward version bump, and leaving known security-constraint bypasses unpatched — even low-probability ones — creates audit and compliance exposure. IGNORE would send the wrong signal for those edge-case deployments.
What to do — in priority order.
- Audit for RewriteValve usage across your fleet — Run a configuration scan for
RewriteValveinserver.xml,context.xml, andWEB-INF/rewrite.configfiles. If zero hits, this CVE is not exploitable in your environment — document and close. This is the single highest-value triage action. As a LOW-severity finding, there is no noisgate mitigation SLA; proceed directly to the remediation window. - Upgrade to Tomcat 9.0.120+ within the 365-day remediation window — The noisgate remediation SLA for LOW is ≤365 days. Bundle this with your next scheduled Tomcat maintenance cycle. For 10.1.x, upgrade to 10.1.57+; for 11.0.x, upgrade to 11.0.24+.
- If RewriteValve IS present, review rewrite rules and security constraints — Check whether any
<security-constraint>patterns depend on URI path segments that pass through RewriteValve rules. If they do, consider adding application-layer authorization checks (Spring Security, Servlet filters) as defense-in-depth while the upgrade is pending. - Ensure a reverse proxy fronts Tomcat — A reverse proxy (nginx, Apache httpd, HAProxy) that normalizes request URIs before forwarding to Tomcat may neutralize the
+-encoding trick. Verify your proxy does not pass raw+characters in path segments to the backend.
- WAF URL-encoding rules alone — generic WAF signatures for percent-encoding attacks won't catch
+in path segments because+is a legal character in URIs. A custom rule specifically targeting+in path positions relevant to your rewrite rules would be needed, which is fragile and application-specific. - Disabling Tomcat security constraints — removing
<security-constraint>entries eliminates the bypass but also removes access control entirely, which is worse than the vulnerability itself. - Upgrading EncryptInterceptor cipher only — switching to AES/GCM/NoPadding addresses CVE-2026-59084 in isolation, but does nothing for CVE-2026-59083. If you're patching, upgrade Tomcat entirely.
Crowdsourced verification payload.
Run this on each Tomcat host (or remotely via SSH/Ansible). Requires read access to the Tomcat installation directory. Invoke: bash check_cve_2026_59083.sh /opt/tomcat (pass CATALINA_HOME as the first argument). No root required unless Tomcat dirs are root-owned.
#!/usr/bin/env bash
# check_cve_2026_59083.sh — Checks for CVE-2026-59083 / CVE-2026-59084 (Tenable 326730)
# Usage: bash check_cve_2026_59083.sh /path/to/catalina_home
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
CATALINA_HOME="${1:-${CATALINA_HOME:-}}"
if [[ -z "$CATALINA_HOME" ]]; then
echo "UNKNOWN — pass CATALINA_HOME as argument or env var"
exit 2
fi
# Extract Tomcat version
VERSION_SH="$CATALINA_HOME/lib/catalina.jar"
if [[ ! -f "$VERSION_SH" ]]; then
# Try version.sh fallback
if [[ -x "$CATALINA_HOME/bin/version.sh" ]]; then
VERSION=$("$CATALINA_HOME/bin/version.sh" 2>/dev/null | grep -oP 'Server number:\s*\K[0-9.]+')
else
echo "UNKNOWN — cannot locate catalina.jar or version.sh in $CATALINA_HOME"
exit 2
fi
else
VERSION=$(unzip -p "$VERSION_SH" org/apache/catalina/util/ServerInfo.properties 2>/dev/null \
| grep -oP 'server\.info=Apache Tomcat/\K[0-9.]+' || true)
fi
if [[ -z "${VERSION:-}" ]]; then
echo "UNKNOWN — could not determine Tomcat version"
exit 2
fi
echo "Detected Tomcat version: $VERSION"
# Version comparison function
version_gte() {
printf '%s\n%s' "$1" "$2" | sort -V | head -n1 | grep -qx "$2"
}
# Check if version is in affected range for 9.0.x
MAJOR=$(echo "$VERSION" | cut -d. -f1)
MINOR=$(echo "$VERSION" | cut -d. -f2)
VULNERABLE=false
case "$MAJOR.$MINOR" in
9.0)
if version_gte "$VERSION" "9.0.120"; then
VULNERABLE=false
else
VULNERABLE=true
fi
;;
10.1)
if version_gte "$VERSION" "10.1.57"; then
VULNERABLE=false
else
VULNERABLE=true
fi
;;
11.0)
if version_gte "$VERSION" "11.0.24"; then
VULNERABLE=false
else
VULNERABLE=true
fi
;;
8.5)
# 8.5.x is EOL; all 8.5.0-8.5.100 are affected, no fix available
if version_gte "$VERSION" "8.5.0"; then
VULNERABLE=true
echo "WARNING: Tomcat 8.5.x is EOL — no patch available, migration required"
fi
;;
*)
echo "UNKNOWN — version $VERSION is outside known affected ranges"
exit 2
;;
esac
# Bonus: check for RewriteValve (the actual prerequisite for CVE-2026-59083)
RW_FOUND=false
for f in "$CATALINA_HOME"/conf/server.xml "$CATALINA_HOME"/conf/context.xml; do
if [[ -f "$f" ]] && grep -qi 'RewriteValve' "$f" 2>/dev/null; then
RW_FOUND=true
echo "NOTE: RewriteValve detected in $f — CVE-2026-59083 is reachable"
fi
done
# Also check webapps for rewrite.config
find "$CATALINA_HOME/webapps" -name 'rewrite.config' -print 2>/dev/null | while read -r rc; do
RW_FOUND=true
echo "NOTE: rewrite.config found at $rc — CVE-2026-59083 is reachable"
done
if [[ "$VULNERABLE" == "true" ]]; then
if [[ "$RW_FOUND" == "false" ]]; then
echo "VULNERABLE (version) — but RewriteValve not detected; CVE-2026-59083 is likely not exploitable"
else
echo "VULNERABLE — version and RewriteValve configuration both match"
fi
exit 1
else
echo "PATCHED — Tomcat $VERSION is at or above the fix version"
exit 0
fiWhat defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.