XSS from disabled Jakarta Faces output escaping

Jakarta Faces output escaping is disabled.

Description

The standard Jakarta Faces components h:outputText, h:outputFormat and h:outputLabel escape characters significant to HTML/XML markup by default. Setting escape to false disables this protection and renders the value as markup. If it contains user input or other untrusted data, an attacker may inject executable HTML or script.

escape="false" alone does not establish an attack: untrusted data must reach that output. Because the setting bypasses the default output encoding, review the data's source and transformations. The Jakarta Faces 4.1 VDL documentation defines true as the default for all three components.

Potential impact

  • Actions performed with the victim's permissions or account impersonation
  • Reading and sending sensitive page data to another destination
  • Phishing interfaces, content modification or redirects to malicious sites

Remediation

  • For ordinary text, omit escape or set escape="true" to retain default escaping.
  • Do not substitute input validation or string filtering for output encoding. Encode values for their actual output context.
  • If user-authored rich HTML is necessary, render only content sanitized on the server with a minimal allow-list policy, such as a maintained OWASP Java HTML Sanitizer. Review the policy and data flow wherever escape="false" is used; a function named sanitize is not proof of safety.
  • Use CSP as an additional defense, not a replacement for output encoding or HTML sanitization.

Examples

Before

html
<ui:composition xmlns:ui="jakarta.faces.facelets"
                xmlns:h="jakarta.faces.html">
  <h:outputText value="#{profile.biography}" escape="false" />
</ui:composition>

After

html
<ui:composition xmlns:ui="jakarta.faces.facelets"
                xmlns:h="jakarta.faces.html">
  <h:outputText value="#{profile.biography}" />
</ui:composition>

Explanation:

  • Before: Renders a user-editable biography with escape="false", so the browser interprets markup in the value.
  • After: Omits escape, using its default true value to encode the same content as HTML text.

References