Skip to content

fix(core): HTML-encode form action in PostbackResult to prevent XSS#1653

Open
tranquac wants to merge 1 commit intoapache:mainfrom
tranquac:fix/postbackresult-xss
Open

fix(core): HTML-encode form action in PostbackResult to prevent XSS#1653
tranquac wants to merge 1 commit intoapache:mainfrom
tranquac:fix/postbackresult-xss

Conversation

@tranquac
Copy link
Copy Markdown

@tranquac tranquac commented Apr 6, 2026

Summary

PostbackResult.doExecute() at line 107 embeds finalLocation into a form action attribute via raw string concatenation without HTML encoding. The response Content-Type is text/html (line 103). A double-quote character in the location breaks out of the attribute, enabling reflected XSS.

This is an encoding inconsistency: form field names and values at lines 218-219 ARE properly URL-encoded via URLEncoder.encode(), but the form action attribute was not encoded at all.

Changes

  • PostbackResult.java: Add encodeHtml() method to escape &, ", <, > in finalLocation before embedding in the HTML form tag. Consistent with the existing encoding approach for form field values.

Impact

When a developer uses PostbackResult with an OGNL expression referencing a user-controllable property (a documented framework feature for dynamic routing), an attacker can inject arbitrary HTML attributes and elements via the form action attribute.

Test

A PoC application with 5 test scenarios verifies the vulnerability and fix. Browser-based testing with Playwright confirms the XSS alert fires before the fix.

PostbackResult.doExecute() embeds finalLocation into a <form action="">
attribute via raw string concatenation without HTML encoding. A double
quote in the location breaks out of the attribute, enabling reflected
XSS. The response Content-Type is text/html (line 103).

This is an encoding inconsistency: form field names and values at lines
218-219 ARE properly URL-encoded via URLEncoder.encode(), but the form
action attribute was not encoded at all.

Add encodeHtml() to escape &, ", <, > in finalLocation before embedding
it in the HTML form tag, consistent with the existing encoding approach
for form field values in the same class.
PrintWriter pw = new PrintWriter(response.getOutputStream());
pw.write("<!DOCTYPE html><html><body><form action=\"" + finalLocation + "\" method=\"POST\">");
String safeLocation = encodeHtml(finalLocation);
pw.write("<!DOCTYPE html><html><body><form action=\"" + safeLocation + "\" method=\"POST\">");
PrintWriter pw = new PrintWriter(response.getOutputStream());
pw.write("<!DOCTYPE html><html><body><form action=\"" + finalLocation + "\" method=\"POST\">");
String safeLocation = encodeHtml(finalLocation);
pw.write("<!DOCTYPE html><html><body><form action=\"" + safeLocation + "\" method=\"POST\">");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants