Skip to content

CVE-2026-50229: Verified Reproduction

CVE-2026-50229: Apache Tomcat examples app XSS in numguess.jsp

CVE-2026-50229 is verified against apache/tomcat · github. Affected versions: Apache Tomcat 11.0.0-M1 through 11.0.22; 10.1.0-M1 through 10.1.55; 9.0.0.M1 through 9.0.118; 8.5.0 through 8.5.100; 7.0.0 through 7.0.109. Vulnerability class: XSS. This medium reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00280.

REPRO-2026-00280 apache/tomcat · github XSS Jul 9, 2026 CVE entry .txt
Severity
MEDIUM
CVSS
6.1
Confidence
HIGH
Reproduced in
16m 6s
Tool calls
146
Spend
$1.42
01 · Overview

What Is CVE-2026-50229?

CVE-2026-50229 is a low-severity reflected/stored cross-site scripting (XSS) vulnerability (CWE-80) in the bundled examples web application shipped with Apache Tomcat. Pruva reproduced it (reproduction REPRO-2026-00280).

02 · Severity & CVSS

CVE-2026-50229 Severity & CVSS Score

CVE-2026-50229 is rated medium severity, with a CVSS base score of 6.1 out of 10.

MEDIUM threat level
6.1 / 10 CVSS base
Weakness CWE-80 — Improper Neutralization of Script-Related HTML Tags in a Web Page ('Cross-site Scripting')

Medium — meaningful risk under specific conditions. Schedule a fix in the normal cycle.

03 · Affected Versions

Affected apache/tomcat Versions

apache/tomcat · github versions Apache Tomcat 11.0.0-M1 through 11.0.22; 10.1.0-M1 through 10.1.55; 9.0.0.M1 through 9.0.118; 8.5.0 through 8.5.100; 7.0.0 through 7.0.109 are affected.

How to Reproduce CVE-2026-50229

$ pruva-verify REPRO-2026-00280
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00280/artifacts/bundle/repro/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-50229

Remote code execution — reproduced
  • reached the target end-to-end
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

HTTP GET parameter hint containing <script>alert(1)</script>

Attack chain
  1. /examples/jsp/num/numguess.jsp in the bundled Tomcat examples web application
Runnable proof: reproduction_steps.sh
Captured evidence: vulnerable startupvulnerable curlvariant vulnerable numguess startupvariant vulnerable numguess curlvariant fixed numguess startupvariant fixed numguess curlvariant fixed colors startupvariant fixed colors curl
How the agent worked 365 events · 146 tool calls · 16 min
16 minDuration
146Tool calls
106Reasoning steps
365Events
3Dead-ends
Agent activity over 16 min
Support
33
Hypothesis
2
Repro
80
Judge
23
Variant
223
0:0016:06

Root Cause and Exploit Chain for CVE-2026-50229

Versions: 7.0.0 through 7.0.109, 8.5.0 through 8.5.100, 9.0.0.M1 through 9.0.118, 10.1.0-M1 through 10.1.55, and 11.0.0-M1 through 11.0.22Fixed: 11.0.23, 10.1.56, 9.0.119 (8.5 and 7.0 are end-of-life)

CVE-2026-50229 is a reflected/stored cross-site scripting (XSS) vulnerability in the bundled examples web application of Apache Tomcat. The vulnerable JSP page webapps/examples/jsp/num/numguess.jsp uses wildcard bean property binding (<jsp:setProperty name="numguess" property="*"/>) against a session-scoped NumberGuessBean. Because the NumberGuessBean exposes a hint property, an attacker can supply a hint request parameter that overwrites the bean's intended hint value. The page later renders the bean's hint value directly into the HTML response using <%= numguess.getHint() %>, which does not escape the content. This allows an attacker to inject arbitrary JavaScript/HTML into the response.

  • Product / Component: Apache Tomcat, bundled examples web application (webapps/examples/jsp/num/numguess.jsp)
  • Affected versions: 7.0.0 through 7.0.109, 8.5.0 through 8.5.100, 9.0.0.M1 through 9.0.118, 10.1.0-M1 through 10.1.55, and 11.0.0-M1 through 11.0.22
  • Fixed versions: 11.0.23, 10.1.56, 9.0.119 (8.5 and 7.0 are end-of-life)
  • Risk level / consequences: Medium. An attacker who can trick a user into visiting a crafted URL can execute JavaScript in the user's browser session in the context of the Tomcat examples application. Because the bean is session-scoped, the payload is also persisted until the session is reset, giving a stored-like behavior.

Impact Parity

  • Disclosed / claimed maximum impact: XSS in the bundled Tomcat examples web application via attacker-controlled request parameters.
  • Reproduced impact from this run: A live HTTP request to the numguess.jsp endpoint on Tomcat 10.1.55 rendered the unescaped <script>alert(1)</script> payload in the HTML response. The same request against Tomcat 10.1.56 did not render the payload because the hint parameter is no longer bound into the session bean.
  • Parity: full — the reproduced behavior matches the disclosed XSS impact.

Root Cause

The root cause is the combination of two design choices in numguess.jsp:

  1. Wildcard bean property binding:

    <jsp:useBean id="numguess" class="num.NumberGuessBean" scope="session"/>
    <jsp:setProperty name="numguess" property="*"/>
    

    property="*" binds every request parameter to a bean property of the same name. This exposes properties other than the intended guess parameter (e.g., hint, answer, success, numGuesses).

  2. Unescaped output:

    Good guess, but nope. Try <b><%= numguess.getHint() %></b>.
    

    The hint value is emitted directly into the HTML without escaping. When an attacker sets hint to HTML/JavaScript, the browser parses and executes it.

Apache fixed this by restricting the property binding to the intended guess parameter:

-<jsp:setProperty name="numguess" property="*"/>
+<jsp:setProperty name="numguess" property="guess"/>

Fix commit: 0d5bdd5b0dd964e9f73e530b7d753462b9bfd1d0 ("Minor optimisation. Only need to set 1 property so don't use wild card.")

Reproduction Steps

  1. Run bundle/repro/reproduction_steps.sh.
  2. The script installs Java if needed, downloads and extracts Apache Tomcat 10.1.55 (vulnerable) and 10.1.56 (fixed), then configures and starts each instance in turn on port 18080.
  3. For each version, the script performs two requests in the same HTTP session:
    • First request: GET /examples/jsp/num/numguess.jsp?guess=abc — establishes a session and advances the game state so the hint branch is rendered.
    • Second request: GET /examples/jsp/num/numguess.jsp?hint=%3Cscript%3Ealert(1)%3C%2Fscript%3E — attempts to bind the attacker-controlled hint parameter into the session bean.
  4. The script inspects the second response for the literal string <script>alert(1)</script>.

Expected evidence:

  • Vulnerable (10.1.55): the second response contains Good guess, but nope. Try <b><script>alert(1)</script></b>.
  • Fixed (10.1.56): the second response contains the default hint (e.g., a number next time) and no attacker-controlled markup.

Evidence

  • bundle/logs/reproduction_steps.log — full script execution log.
  • bundle/repro/vulnerable_resp2.html — HTTP response from the vulnerable Tomcat 10.1.55 showing the unescaped payload.
  • bundle/repro/fixed_resp2.html — HTTP response from the fixed Tomcat 10.1.56 showing the payload is absent.
  • bundle/repro/runtime_manifest.json — runtime evidence manifest.

Key excerpt from vulnerable_resp2.html:

Good guess, but nope.  Try <b><script>alert(1)</script></b>.

Key excerpt from fixed_resp2.html:

Good guess, but nope.  Try <b>a number next time</b>.

Environment:

  • OpenJDK 25.0.3 (installed via default-jdk package)
  • Apache Tomcat 10.1.55 and 10.1.56 binary distributions from https://archive.apache.org/dist/tomcat/

Recommendations / Next Steps

  • Upgrade to a fixed Tomcat version (10.1.56+, 9.0.119+, or 11.0.23+).
  • Remove or disable the examples web application in production environments; it is intended for demonstration only.
  • Avoid wildcard bean property binding (property="*") when the request can contain untrusted parameters; explicitly whitelist the parameters the application intends to bind.
  • Escape output when rendering dynamic content, or use a framework that escapes expression-language output by default.
  • Add regression tests that verify untrusted request parameters are not bound into session beans and are not reflected unescaped in responses.

Additional Notes

  • The reproduction script is idempotent: it reuses cached Tomcat archives, reconfigures ports deterministically, and cleanly stops each instance before starting the next one.
  • The script was run twice consecutively and produced the same confirmed result both times.
  • The examples application is typically not deployed in production, which limits real-world exploitability, but the vulnerability is real in the shipped product.

CVE-2026-50229 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:003:05
0:00
session startedaccounts/fireworks/models/kimi-k2p7-code · CVE-2026-50229 · REPRO-20
0:02
0:03
web search
0:06
0:07
0:18
0:19
0:21
0:22
0:31
0:33
web search
0:34
0:36
0:38
0:39
0:45
0:46
1:08
1:09
web search
2:25
2:25
extract_facts
no facts extracted
2:27
2:27
2:27
supportrepro
3:03
3:05
3:05
08 · How to Fix

How to Fix CVE-2026-50229

Coming soon

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

10 · FAQ

FAQ: CVE-2026-50229

How does the CVE-2026-50229 XSS attack work?

An attacker crafts a URL to the numguess.jsp example page with a hint parameter containing HTML/JavaScript. The wildcard property binding lets this attacker-controlled value overwrite the session-scoped bean's hint field, which is then echoed unescaped into the HTML response, executing the injected script in the victim's browser. Because the bean is session-scoped, the payload persists until the session resets, giving stored-like behavior.

Which Apache Tomcat versions are affected by CVE-2026-50229, and where is it fixed?

Affected versions are 7.0.0 through 7.0.109, 8.5.0 through 8.5.100, 9.0.0.M1 through 9.0.118, 10.1.0-M1 through 10.1.55, and 11.0.0-M1 through 11.0.22. It is fixed in 11.0.23, 10.1.56, and 9.0.119; the 8.5 and 7.0 lines are end-of-life and will not receive a fix.

How severe is CVE-2026-50229?

It is rated low severity by Pruva. It requires an attacker to trick a user into visiting a crafted URL against the bundled Tomcat examples application, which is not typically deployed in production.

How can I reproduce CVE-2026-50229?

Download the verified script from this page and run it in an isolated environment against an affected Tomcat build with the examples web application deployed. It submits a crafted hint parameter to numguess.jsp and shows the payload reflected unescaped in the HTML response, then confirms the patched version restricts property binding to the intended guess parameter.
11 · References

References for CVE-2026-50229

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