← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
tenable:166906 · CWE-444 · Disclosed 2022-10-31

Apache Tomcat 9

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

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.

"This is a noisy version hit: Tomcat 9 needs a non-default setting and a weak reverse proxy before the bug is real."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Find a proxied Tomcat edge

The attacker first needs a reachable HTTP path where Tomcat is serving behind a front-end component such as Nginx, Apache httpd, HAProxy, a cloud load balancer, or an ADC. Tools like http-request-smuggler or smuggler are then used to fingerprint parser discrepancies and keep-alive behavior at the edge.
Conditions required:
  • 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
Where this breaks in practice:
  • 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
Detection/coverage: External scanners can find 'possible desync' patterns, but version-only Nessus checks like plugin 166906 do not prove the proxy chain is exploitable.
STEP 02

Need the non-default Tomcat 9 parser setting

For Tomcat 9, exploitation requires 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.
Conditions required:
  • Tomcat 9.0.0-M1 to 9.0.67
  • rejectIllegalHeader="false" configured on the relevant connector
Where this breaks in practice:
  • 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
Detection/coverage: Best validated locally by reading conf/server.xml and connector attributes; remote scanners usually miss this config prerequisite.
STEP 03

Require a second parser mistake in the proxy

Even with the Tomcat-side setting weakened, the attacker still needs the front-end proxy to disagree with Tomcat about where one request ends and the next begins. Burp HTTP Request Smuggler and smuggler automate CL/TE-style and parser-differential probing to test that mismatch.
Conditions required:
  • Reverse proxy forwards malformed requests instead of rejecting them
  • Backend connection reuse allows desynchronization to matter
Where this breaks in practice:
  • 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
Detection/coverage: Request-smuggling testing is specialized and noisy; most infra vulnerability scanners do not verify the full proxy/backend chain.
STEP 04

Turn desync into useful impact

If the chain holds, the attacker can try cache poisoning, request prefix injection, WAF bypass, or session confusion against adjacent users or backend endpoints. The impact is usually integrity/control-plane confusion, not instant server takeover.
Conditions required:
  • A meaningful target route exists behind the proxy
  • The application behavior is exploitable via desynchronized requests
Where this breaks in practice:
  • 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
Detection/coverage: Look for anomalous 400/408/502 patterns, backend/proxy request count mismatches, and weird header-length parsing failures in reverse proxy logs.
03 · Intelligence Metadata

The supporting signals.

Primary CVECVE-2022-42252 — Apache Tomcat request smuggling via malformed Content-Length
In-the-wild statusNo 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 availabilityYes, 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.
EPSSOpenCVE currently shows EPSS 0.00157 for CVE-2022-42252, which is a very low exploitation-likelihood signal.
KEV status and datesNot 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 missesNVD/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 versionsApache 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 backportsUpstream 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 realityInternet-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 / disclosureApache 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.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.1/10)

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.

HIGH The Tomcat 9 non-default configuration requirement is real and materially reduces exposure
MEDIUM Actual prevalence of risky reverse-proxy/parser combinations in enterprise estates

Why this verdict

  • Non-default on Tomcat 9: Apache says rejectIllegalHeader=false is *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.

05 · Compensating Control

What to do — in priority order.

  1. 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.
  2. Make the proxy reject malformed lengths — Enforce strict header parsing on the reverse proxy or load balancer so malformed Content-Length requests die at the edge. This breaks the second prerequisite in the chain; for LOW, fold it into normal hardening work rather than emergency change.
  3. 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.
What doesn't work
  • A version-only exception without checking config does not solve the problem; you need to know whether rejectIllegalHeader=false was 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.
06 · Verification

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.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/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()
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: treat this as a configuration-validation task first, patch task second. For a LOW reassessment there is no noisgate mitigation SLA and no noisgate remediation SLA — treat as backlog hygiene: validate whether any Tomcat 9 connectors were explicitly set to 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

  1. Tenable plugin 166906
  2. Apache Tomcat 9 security page
  3. NVD CVE-2022-42252
  4. CISA KEV catalog
  5. OpenCVE entry with EPSS/KEV status
  6. PortSwigger HTTP Request Smuggler
  7. Ubuntu CVE tracker
  8. Ubuntu USN-6880-1
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.