Like a bad spare key that only works if two different doors were both installed wrong
This plugin is tracking CVE-2022-42252, an HTTP request smuggling flaw in Apache Tomcat. For the Tomcat 9 branch, the affected range is 9.0.0-M1 through 9.0.67, fixed in 9.0.68 on 2022-10-07. But Tomcat 9 is only exposed if someone explicitly set rejectIllegalHeader="false"; Apache's own advisory says that is not the default for Tomcat 9, even though Tenable's generic plugin text can read like a straight version-only issue.
The vendor-high treatment does not match real enterprise risk for Tomcat 9. This is a classic desync bug with stacked prerequisites: the target must be on a vulnerable version, must have a non-default parser setting, and must sit behind a reverse proxy that also mishandles the malformed Content-Length header. No KEV listing, no strong exploitation signal, and no direct RCE keeps this out of your urgent queue unless you've knowingly weakened header validation.
4 steps from start to impact.
Find a proxied Tomcat edge
http-request-smuggler or smuggler are then used to fingerprint parser discrepancies and keep-alive behavior at the edge.- Unauthenticated remote network reachability to the application
- Tomcat is deployed behind a reverse proxy or load balancer
- Persistent connections are in use across the proxy/backend path
- Many enterprises terminate at modern proxies that normalize or reject malformed headers before Tomcat sees them
- Direct-to-Tomcat deployments are common internally but then this specific desync precondition disappears
- WAF/CDN/LB stacks often collapse connections in ways that kill smuggling reliability
Need the non-default Tomcat 9 parser setting
rejectIllegalHeader=false so Tomcat will accept an invalid Content-Length header that it should otherwise reject. Apache's Tomcat 9 advisory explicitly says this is not the default, which is the single biggest reason this CVE is over-scored in generic patch reports.- Tomcat 9.0.0-M1 to 9.0.67
rejectIllegalHeader="false"configured on the relevant connector
- This is a manual hardening regression, not the Tomcat 9 default state
- Many estates inherited scanner findings from package versions without validating connector config
- Containers and vendor appliances may backport fixes or keep the safe default even when banner versions look old
conf/server.xml and connector attributes; remote scanners usually miss this config prerequisite.Require a second parser mistake in the proxy
Burp HTTP Request Smuggler and smuggler automate CL/TE-style and parser-differential probing to test that mismatch.- Reverse proxy forwards malformed requests instead of rejecting them
- Backend connection reuse allows desynchronization to matter
- This is an architectural dependency outside Tomcat itself
- Different proxies, CDN layers, and service meshes often sanitize away the malformed header
- Even 'vulnerable' stacks can be inconsistent and unreliable to weaponize in production
Turn desync into useful impact
- A meaningful target route exists behind the proxy
- The application behavior is exploitable via desynchronized requests
- Many apps offer no easy cache-poisoning or auth-bypass primitive even when desync exists
- Impact often depends on endpoint-specific quirks rather than the Tomcat bug alone
- Operationally, exploitation is less turnkey than an unauthenticated RCE
The supporting signals.
| Primary CVE | CVE-2022-42252 — Apache Tomcat request smuggling via malformed Content-Length |
|---|---|
| In-the-wild status | No KEV listing found in CISA's Known Exploited Vulnerabilities Catalog, and I found no authoritative active-exploitation bulletin tied to this CVE. |
| Proof-of-concept availability | Yes, generic tooling exists: PortSwigger's HTTP Request Smuggler and smuggler-style tooling are enough to test/weaponize desync conditions, even without a CVE-specific exploit. |
| EPSS | OpenCVE currently shows EPSS 0.00157 for CVE-2022-42252, which is a very low exploitation-likelihood signal. |
| KEV status and dates | Not in KEV as of the current CISA catalog page. Public disclosure was 2022-10-31 per Apache; NVD published the record on 2022-11-01. |
| CVSS and what it misses | NVD/CISA ADP score it 7.5 HIGH with CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N. That base score treats the bug like a broadly reachable network parser flaw, but it does not price in the Tomcat 9 non-default config and the required proxy-side parser failure. |
| Affected versions | Apache states Tomcat 9.0.0-M1 to 9.0.67 are affected, but only when rejectIllegalHeader=false. Tenable plugin 166906 flags the version range broadly. |
| Fixed versions and backports | Upstream fix is 9.0.68. Ubuntu tracks fixes via backports rather than upstream version strings, including USN-6880-1, so package version alone must be interpreted in distro context. |
| Exposure/scanning reality | Internet-wide exposure is hard to count meaningfully because exploitability depends on a proxy/backend pair plus a Tomcat config flag. In practice, version-only scanning overcounts; this is more of a configuration-validation problem than a pure inventory problem. |
| Reporter / disclosure | Apache Tomcat says the issue was reported to the Tomcat Security Team on 2022-09-29 and made public on 2022-10-31 in the Tomcat 9 security page. |
noisgate verdict.
The decisive downgrade is that Tomcat 9 is not vulnerable by default; an operator must have explicitly set rejectIllegalHeader=false first. After that, exploitation still depends on a second failure in the reverse proxy layer, so the version-only finding dramatically overstates real fleet risk.
Why this verdict
- Non-default on Tomcat 9: Apache says
rejectIllegalHeader=falseis *not* the default for Tomcat 9, so the scanner is flagging many hosts that are version-matched but not actually exposed. - Posture depends on architecture: the bug only matters when a reverse proxy in front of Tomcat also accepts the malformed header and desynchronizes request boundaries.
- Impact is indirect: this is request smuggling with integrity-side effects like cache poisoning or WAF bypass, not a clean unauthenticated RCE primitive.
Why not higher?
There is no credible evidence here of mass exploitation, no KEV listing, and no default-vulnerable state for Tomcat 9. Real exploitability requires two separate parser mistakes across two layers of the stack, which sharply narrows the reachable population.
Why not lower?
I did not push this to IGNORE because some enterprises really do run Tomcat behind proxies with compatibility-driven connector tweaks, and when the chain lines up an unauthenticated attacker can still cause meaningful request-routing and cache integrity problems. It merits validation and cleanup; it just does not merit panic.
What to do — in priority order.
- Audit connector settings — Check every Tomcat 9 connector for
rejectIllegalHeader="false"and revert to the safe default unless there is a documented business dependency. For a LOW verdict there is no SLA; treat this as backlog hygiene, but validate internet-facing and shared-platform instances first. - Make the proxy reject malformed lengths — Enforce strict header parsing on the reverse proxy or load balancer so malformed
Content-Lengthrequests die at the edge. This breaks the second prerequisite in the chain; for LOW, fold it into normal hardening work rather than emergency change. - Prioritize externally reachable apps — If you have old Tomcat 9 behind internet-facing proxies, validate those first because they are the only population with plausible adversary reachability. Internal-only middleware on safe defaults can stay in routine patch flow.
- A version-only exception without checking config does not solve the problem; you need to know whether
rejectIllegalHeader=falsewas set. - A generic WAF is not a dependable fix for request smuggling because the issue is parser disagreement between layers, not just a bad URL or signature match.
- Hiding banners or changing server headers does nothing; this is about request parsing behavior, not product fingerprinting.
Crowdsourced verification payload.
Run this on the target Tomcat host or inside the container image with read access to the Tomcat install and conf/. Invoke it as python3 check_tomcat_cve_2022_42252.py /opt/tomcat or point it at %CATALINA_HOME% on Windows. No admin rights are required if the user can read the Tomcat directory tree.
#!/usr/bin/env python3
# check_tomcat_cve_2022_42252.py
# Detects Tomcat 9 exposure to CVE-2022-42252 based on version + connector config.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
import os
import re
import sys
import zipfile
from pathlib import Path
AFFECTED_FIXED = (9, 0, 68)
def parse_version_string(s):
if not s:
return None
m = re.search(r'(\d+)\.(\d+)\.(\d+)', s)
if not m:
return None
return tuple(int(x) for x in m.groups())
def find_tomcat_version(base):
# 1) RELEASE-NOTES / RUNNING.txt
for rel in ['RELEASE-NOTES', 'RUNNING.txt', 'RELEASE-NOTES.txt']:
p = base / rel
if p.is_file():
try:
txt = p.read_text(errors='ignore')
v = parse_version_string(txt)
if v:
return v, f'{p}'
except Exception:
pass
# 2) catalina.jar -> ServerInfo.properties
jar = base / 'lib' / 'catalina.jar'
if jar.is_file():
try:
with zipfile.ZipFile(jar, 'r') as zf:
for name in [
'org/apache/catalina/util/ServerInfo.properties',
'org/apache/catalina/util/ServerInfo.properties.default'
]:
if name in zf.namelist():
data = zf.read(name).decode('utf-8', errors='ignore')
for line in data.splitlines():
if line.strip().startswith('server.number='):
v = parse_version_string(line.split('=', 1)[1].strip())
if v:
return v, f'{jar}!{name}'
except Exception:
pass
return None, None
def is_tomcat9(v):
return v is not None and len(v) == 3 and v[0] == 9
def scan_reject_illegal_header_false(base):
hits = []
conf = base / 'conf'
if not conf.exists():
return hits
for p in conf.rglob('*.xml'):
try:
txt = p.read_text(errors='ignore')
except Exception:
continue
if re.search(r'rejectIllegalHeader\s*=\s*["\']false["\']', txt, re.IGNORECASE):
hits.append(str(p))
return hits
def main():
arg = None
if len(sys.argv) > 1:
arg = sys.argv[1]
else:
arg = os.environ.get('CATALINA_BASE') or os.environ.get('CATALINA_HOME') or '.'
base = Path(arg).expanduser().resolve()
if not base.exists():
print(f'UNKNOWN - Path not found: {base}')
sys.exit(2)
version, source = find_tomcat_version(base)
if version is None:
print(f'UNKNOWN - Could not determine Tomcat version under {base}')
sys.exit(2)
if not is_tomcat9(version):
print(f'UNKNOWN - Detected Tomcat version {version[0]}.{version[1]}.{version[2]} (script is scoped to Tomcat 9 / plugin 166906)')
sys.exit(2)
hits = scan_reject_illegal_header_false(base)
ver_str = f'{version[0]}.{version[1]}.{version[2]}'
if version >= AFFECTED_FIXED:
print(f'PATCHED - Tomcat {ver_str} >= 9.0.68 (source: {source})')
sys.exit(0)
# For Tomcat 9, Apache states the vulnerable setting is non-default.
if hits:
print(f'VULNERABLE - Tomcat {ver_str} < 9.0.68 and rejectIllegalHeader="false" found in: {", ".join(hits)}')
sys.exit(1)
else:
print(f'PATCHED - Tomcat {ver_str} < 9.0.68 but no rejectIllegalHeader="false" found under {base}/conf; Tomcat 9 is not vulnerable by default')
sys.exit(0)
if __name__ == '__main__':
main()
If you remember one thing.
rejectIllegalHeader=false, focus first on internet-facing apps behind reverse proxies, and only prioritize upgrade to 9.0.68+ on the subset that actually meets the risky config/architecture conditions; otherwise keep it in the normal maintenance stream and document the downgrade rationale in the scanner exception notes.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.