Last updated Mar 27, 2024

Advanced HTML encoding

This page contains information about advanced HTML encoding for Confluence plugins.

Advanced automatic encoding topics

Collection inheritance

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:
    • java.util.List#get(index)
    • java.util.Map#get(key)
  • 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 #foreach statement.)

HtmlFragment

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.

1
2
HtmlFragment aHtmlFragment = new HtmlFragment("<span>This string contains literal HTML</span">);
HtmlFragment anotherHtmlFragment = new HtmlFragment(new MyHtmlClass());

The HtmlFragment class' 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

The 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.

PossibleIncorrectHtmlEncodingEventHandler

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 INFO.

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.

Rate this page: