[ 
https://issues.apache.org/jira/browse/WW-5639?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18097276#comment-18097276
 ] 

Greg Huber edited comment on WW-5639 at 7/20/26 6:46 AM:
---------------------------------------------------------

How about something like this:

[https://github.com/gregh3269/struts/tree/STRUTS_6_10_0-WW-5639]

 
Then all I need to do is to add to my struts.xml

 <bean type="org.apache.struts2.components.escape.EscapeStrategy" 
name="myEscapeStratergy" class="my.util.DefaultEscapeAdapter" />

and struts.property

struts.escape.strategy=myEscapeStratergy

Then by using my on implementation I can expose oneself to all sorts of 
security risks, without changing anything in Struts.
 
{code:java}
package my.util;
....
import org.apache.struts2.components.escape.EscapeStrategy;
public class DefaultEscapeAdapter implements EscapeStrategy {

        @Override
        public String escape(boolean escapeHtml, boolean escapeJavaScript,
                        boolean escapeXml, boolean escapeCsv, String value) {
                String result = value;
                if (escapeHtml) {
                        // result = StringEscapeUtils.escapeHtml4(result);

                        // 
https://jsoup.org/apidocs/org/jsoup/safety/Safelist#simpleText()
                        result = Jsoup.clean(value,
                                        "",
                                        Safelist.simpleText().addTags("br"),
                                        new 
Document.OutputSettings().prettyPrint(false));

                }
                if (escapeJavaScript) {
                        result = StringEscapeUtils.escapeEcmaScript(result);
                }
                if (escapeXml) {
                        result = StringEscapeUtils.escapeXml10(result);
                }
                if (escapeCsv) {
                        result = StringEscapeUtils.escapeCsv(result);
                }

                return result;
        }

}

{code}
 

 


was (Author: gregh99):
How about something like this:

[https://github.com/gregh3269/struts/tree/STRUTS_6_10_0-WW-5639]

 
Then all I need to do is to add to my struts.xml

 <bean type="org.apache.struts2.components.escape.EscapeStrategy" 
name="myEscapeStratergy" class="my.util.DefaultEscapeAdapter" />

and struts.property

struts.escape.strategy=myEscapeStratergy

Then by using my on implementation I can expose oneself to all sorts of 
security risks, without changing anything in Struts.
 
{code:java}
package my.util;
....
import org.apache.struts2.components.escape.EscapeStrategy;
public class DefaultEscapeAdapter implements EscapeStrategy {

        @Override
        public String escape(boolean escapeHtml, boolean escapeJavaScript,
                        boolean escapeXml, boolean escapeCsv, String value) {
                String result = value;
                if (escapeHtml) {
                        // result = StringEscapeUtils.escapeHtml4(result);

                        // 
https://jsoup.org/apidocs/org/jsoup/safety/Safelist#simpleText()
                        result = Jsoup.clean(value,
                                        
EventsRuntimeConfig.getAbsoluteContextURL(),
                                        Safelist.simpleText().addTags("br"),
                                        new 
Document.OutputSettings().prettyPrint(false));

                }
                if (escapeJavaScript) {
                        result = StringEscapeUtils.escapeEcmaScript(result);
                }
                if (escapeXml) {
                        result = StringEscapeUtils.escapeXml10(result);
                }
                if (escapeCsv) {
                        result = StringEscapeUtils.escapeCsv(result);
                }

                return result;
        }

}

{code}
 

 

> <s:property> escape options should be mutually exclusive
> --------------------------------------------------------
>
>                 Key: WW-5639
>                 URL: https://issues.apache.org/jira/browse/WW-5639
>             Project: Struts 2
>          Issue Type: Improvement
>          Components: Core Tags
>            Reporter: Lukasz Lenart
>            Priority: Major
>             Fix For: 7.3.0
>
>
> The {{<s:property>}} tag exposes four boolean escape attributes — 
> {{escapeHtml}}
> (default {{true}}), {{escapeJavaScript}}, {{escapeXml}} and {{escapeCsv}} 
> (default
> {{false}}). {{Property.prepare()}} applies them *cumulatively*, chaining one
> escaper after another. Chaining escapers that target different output contexts
> produces corrupt output:
> * {{escapeHtml=false escapeJavaScript=true}} on {{<b></b>}} yields 
> {{<b><\/b>}},
>   because {{escapeEcmaScript}} escapes {{/}} as {{\/}}. The closing tag is 
> broken
>   and the rendered layout is damaged. Allowing HTML markup ({{<b>}}, 
> {{<strong>}},
>   {{<em>}}) while also JavaScript-escaping is impossible — the two contexts
>   conflict by nature.
> * Leaving {{escapeHtml=true}} (the default) while also setting 
> {{escapeXml=true}}
>   or {{escapeCsv=true}} double-escapes entities ({{escapeHtml4}} turns {{&}} 
> into
>   {{&amp;}}, then {{escapeXml10}} escapes the {{&}} again).
> h3. Note on security
> {{escapeJavaScript}} ({{escapeEcmaScript}}) escapes only {{' " \ /}} and 
> control
> characters; it does *not* escape {{<}}, {{>}} or {{&}}, so it is not an
> HTML-safety mechanism. The real exposure is that {{escapeHtml=false}} emits 
> raw,
> unescaped HTML — an XSS risk unless the value is fully trusted.
> h3. Proposed fix
> Make the four escape options mutually exclusive. Apply exactly one escaper,
> selected by first-match precedence:
> {noformat}
> escapeHtml -> escapeJavaScript -> escapeXml -> escapeCsv
> {noformat}
> HTML has the highest precedence. Since {{escapeHtml}} defaults to {{true}}, 
> the
> default behavior (HTML escaping only) is unchanged, and the established 
> pattern of
> "set {{escapeHtml=false}} plus the one escaper you want" is preserved. The 
> only
> outputs that change are configurations that were already producing corrupt
> double-escaped results.
> h3. Additionally
> * When {{devMode}} is enabled and more than one escape flag is set, log a 
> warning
>   naming which escaper was applied and noting the options are mutually 
> exclusive.
> * Update the {{escapeHtml}} / {{escapeJavaScript}} {{@StrutsTagAttribute}}
>   descriptions and the class JavaDoc: {{escapeHtml=false}} emits raw HTML (XSS
>   risk unless the value is trusted); {{escapeJavaScript}} targets a JS
>   string-literal context, not HTML, and escapes {{/}} as {{\/}} so it cannot
>   coexist with surviving HTML markup.
> This is a behavior change and should ship in *7.3.x* (minor). The public docs 
> page
> at [https://struts.apache.org/tag-developers/property-tag] is updated 
> separately
> in the {{struts-site}} repo.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to