Advanced HTML encoding
This page contains information about advanced HTML encoding for Confluence plugins.
On this page:
Advanced automatic encoding topics
In some cases a method may return a collection of values, each of which contain HTML markup to be treated literally in a Velocity template. If a collection returning method is marked as
HtmlSafe, then all of its members will be treated as
HtmlSafe as well should they be written to a Velocity template.
More precisely, a value retrieved from a
HtmlSafe collection will be treated as
HtmlSafe in the following situations:
- The element is retrieved via:
- The element is reached via an iterator returned by
java.util.Collection#iterator()(as is the case when a collection is used with the Velocity
One of the things that has become painfully obvious in the implementation of this system is the inadequacy of the
String class for returning markup. The need for a
HtmlSafe annotation is only necessary because a
String return type does not convey any information about the data returned other than it is a sequence of characters. The
com.atlassian.confluence.velocity.htmlsafe.HtmlFragment class is a type that can be used to indicate that the
toString() method of a particular object returns markup to be interpreted as literal HTML during rendering.
toString() method delegates to the wrapped object's
toString() method and will be treated as being safe for use in HTML templates. This is useful for adding your own
HtmlSafe values directly to a Velocity context or as a return type for methods returning HTML markup.
VelocityUtils HTML detection heuristic
com.atlassian.confluence.utils.VelocityUtils class defines methods of the form
getRenderedTemplate for convenient rendering of a template to a
String. Unfortunately the only information available to this mechanism is the template name and Velocity context, neither of which indicate directly whether the template is to be used for HTML output. It is using HTML encoding by default, unless you explicitly opt-out using the
#disableAntiXSS() directive. Opting out is recommended only for troubleshooting purposes.
To help track down any Velocity reference that might be encoded incorrectly, Confluence attaches a logging event listener to the Velocity context. This event listener will print the reference name and the template that contains the reference if the reference value contains HTML like markup (either element markup or encoded entities) but the reference hasn't been marked as HTML safe. Naturally some values may contain HTML markup that are not meant to be interpreted as literal HTML, as is the case in HTML injection attacks.
This event listener will only be active if the log4j logger category
com.atlassian.confluence.velocity.htmlsafe.PossibleIncorrectHtmlEncodingEventHandler has been set to log at
The boxing uberspect
Confluence employs a specialisation of Velocity's pluggable, federated introspection strategy known as an
Uberspect. The Velocity runtime delegates all method calls, property accesses and iterator strategy retrieval via the configured uberspect. The default Velocity uberspect implementation provides all of the facilities to call methods and access properties of objects in the Velocity context by making heavy use of the Java reflection API. It also provides the mechanism for case insensitive property access, Velocity's map getter syntactic sugar and uses an internal introspection cache to optimise performance.
To enable the tracking of values retrieved from
HtmlSafe sources, Confluence is configured to use a specialised uberspect that boxes any
ReturnValueAnnotation annotations with the method return value. Return values from method calls that do not have any such annotations are treated exactly as before. Of course any of these uberspect boxed values may be subsequently used as arguments or targets of other method calls, so the annotation boxing uberspect is also responsible for unboxing these values before a method is executed, providing a mostly transparent operation.
For those developers who are more interested in the exact implementation details, you will want to examine the source of the classes in the new
com.atlassian.confluence.velocity.introspection package, with the
AnnotationBoxingUberspect being the best place to start.