Reputation: 4310
It is very good practice in HTML template engines to HTML-escape by default placeholder text to help prevent XSS (cross-site scripting) attacks. Is it possible to achieve this behavior in StringTemplate?
I have tried to register custom AttributeRenderer
which escapes HTML unless format
is "raw"
:
stg.registerRenderer(String.class, new AttributeRenderer() {
@Override
public String toString(Object o, String format, Locale locale) {
String s = (String)o;
return Objects.equals(format, "raw") ? s : StringEscapeUtils.escapeHtml4(s);
}
});
But it fails because in this case StringTemlate escapes not only placeholder text but also template text itself. For example this template:
example(title, content) ::= <<
<html>
<head>
<title>$title$</title>
</head>
<body>
$content; format = "raw"$
</body>
</html>
>>
Is rendered as:
<html>
<head>
<title>Example Title</title>
</head>
<body>
<p>Not escaped because of <code>format = "raw"</code>.</p>
</body>
</html>
Can anybody help?
Upvotes: 4
Views: 1511
Reputation: 8005
There is no good solution to encode by default. The template is passed through the AttributeRenderer for the string data type, and there is no context information to detect if it is processing the template or a variable. So all strings, including the template, are encoded by default since you cannot specify "raw" for the template.
An alternative solution is to use format="xml-encode"
in the variables that need to be encoded. The built-in StringRenderer
has support for several formats:
So your example would be:
example(title, content) ::= <<
<html>
<head>
<title>$title; format="xml-encode"$</title>
</head>
<body>
$content$
</body>
</html>
>>
In order to encode by default, you have limited options. The alternatives are:
String
) for your variables, so you can register your HtmlEscapeStringRenderer
for the custom data type. This is difficult if you use complex objects as variables that are already using standard strings.title
(escaped) and title_raw
(raw). You do not need a custom AttributeRenderer in this case. StringTemplate has a strict view/model separation and you need to have the model populated before it is rendered with both the raw and escaped values.Neither option is particularly desirable, but I do not see any other alternatives with StringTemplate4.
Upvotes: 3