Output Text: Reworking XSS-Sanitized HTML Bindings

Follow

Problem

Due to security concerns, Brazos UI controls displaying HTML are currently not permitted to include elements, attributes, or content that result in executable JavaScript. Cross-Site Scripting (XSS) protections will remove elements and attributes that are not on a white-list from the bound HTML. Therefore, an IBM BPM Human Service developed prior to version 5.4.0 of the Brazos UI Toolkit will no longer work as expected in the latest versions if any of the protected controls utilize non-permitted HTML. For example, an Output Text displaying an HTML string of an anchor tag with an onClick attribute will be rendered as a link but will no longer have the onClick action.

Background

The Output Text control has a configuration option to interpret its data binding as HTML. However, this set up is vulnerable to Cross-Site Scripting (XSS) as a malicious user could enter data into the system that can be run on another coach later in the Process. In order to limit the opportunities for XSS, the Output Text is currently limited to a list of supported elements and attributes; anything else is removed prior to rendering the coach. This "disarms" potentially malicious code by preventing its inclusion in the HTML of the page.

See this article for a list of permitted tags and attributes. Any IBM BPM Human Service developed prior to version 5.4.0 of the Brazos UI toolkit which also associated HTML with Brazos UI controls' bindings or configuration options may no longer work as expected in the latest versions of the toolkit. However, even beyond the XSS vulnerabilities, these solutions typically suffered from several problems in design and implementation as data, functions, and HTML structure were mixed together into a single String variable that still required supporting script blocks for assembly and functionality.

Solution

A custom Coach View (CV) can be used to construct complex or interactive pieces of HTML. Using the Output Text control to display HTML is still an appropriate option for many basic use cases but when that falls short a custom control is advised. Using a custom CV also has two advantages over previous implementations that may have used scripting with HTML in Output Texts:

  1. It separates the concerns of data from structure and function. Having the Output Text render a complex component requires that the Task data, as well as HTML structure and JavaScript references, all be rolled into a single variable. By using a custom CV, the data can be kept isolated as inputs (either the binding or configuration options) while the details of HTML structure and behavior are maintained within the control itself.
  2. It improves maintainability and reusability. When relying on an HTML string to be interpreted by the Output Text, the individual contributing components are spread out within the Human Service. A script block may be assembling the string while a Custom HTML block is defining the function; there is no single unit that encapsulates the purpose of the code. This can also result in repeated code as these parts are copy and pasted across Coaches. In contrast, Coach Views encapsulate desired functionality into self-sufficient, portable, and reusable units. Then, within the container of the CV, the necessary parts are easily located:data is passed in and out through Variables, the structure is defined in the Layout, and the functionality is managed with Behavior. The reusability can also be elevated via shared Toolkits.

Example: Reworking onClick Events with a Custom Coach View

As a simplified example, an Output-Text-bound HTML string designed to open a Service with an exposed URL can be adapted to work from a custom CV.

XSS Sanitized Binding

Prior to v5.4.0 of the Brazos UI toolkit, a designer could use an onClick event to produce a link for opening a Service from a Table while passing in row-specific data. While a similar outcome could be achieved in several different ways, for the sake of this example a function is being used.

The Output Text on the Table would be bound to  tw.local.tabledata.currentItem.launchOnClick which is set by this script snippet:

tw.local.tableData[i].launchOnClick = '<a href=\"javascript:void(0)\" 
    onClick=\"openTask(\'' + tw.local.tableData[i].serviceID + '\', \'' +
    tw.local.tableData[i].taskInput + '\');\">' + tw.local.tableData[i].taskName + '</a>';

As can be seen, not only is this script mixing together data, structure, and function into a single variable, it's also rather hard to read. This snippet also doesn't encapsulate the full necessary supporting components that make this work. The function call, for example, needs to be defined so that it is accessible to the running coach. So in a custom HTML block or in an included JS file, we also have to have this function definition:

var windowObjectReference;
function openTask(serviceID, taskInput){
var taskURL = "../teamworks/executecf?" + serviceID + "&tw.local.input1=" + taskInput;
windowObjectReference = window.open(taskURL, "ExecutableURLService_Window");
}

The Output Text binding from the first row produces:

<a href="javascript:void(0)" onclick="openTask('modelID=1.f28fd552-577d-4850-b557-378741a59108&amp;branchID=2063.52f7cdab-4fc9-4f73-b734-afd4899468b9', 'Input from row 0');">Service exposed by URL, row 0</a>

Which results in this displayed cell which will open a startable service that is exposed by URL while passing in a small bit of data:

OnClickAsDisplayed.png

When upgrading to the latest versions of Brazos UI, however, the backing HTML is sanitized. The link itself is displayed the same on the running coach, but it is nonfunctional. The href is removed for having executable javascript (normally href is a permitted attribute) and the onClick is removed because it is not on the white-list. The resulting HTML looks like this:

<a>Service exposed by URL, row 0</a>

Pivoting to a Custom Coach View

Breaking the desired outcome into its basic components of data, structure, and function can help us organize the implementation of the custom CV for generating the clickable link. See the general guidelines for implementing customizations with Brazos UI.

Data

The relevant data should be set as the binding or configuration options of the CV, as appropriate for the type. Reusability might be a consideration when determining how to interface with the data.

CVVariables.png

Structure

The HTML structure is defined in the Layout tab. The basic desired outcome here is the generation of a clickable link. For this example, we can accomplish that with a simple anchor tag that we modify later with jQuery. In a custom HTML block of the Layout:

<a class='scriptedLink'></a>

Function

The actions of assembling the URL will be managed under the Behavior tab. In this example we want to add the display text to the link and make sure that clicking on it carries out the desired action:

Inline Javascript

var linkText = this.context.binding.get("value");
var serviceID = this.context.options.serviceID.get("value");
var taskInput = this.context.options.taskData.get("value");
var windowObjectReference;

function openTask(serviceID, taskInput){
    console.log("In openTask function");
    var taskURL = "../teamworks/executecf?" + serviceID + "&" + taskInput.get("name") + "=" + taskInput.get("value");
    windowObjectReference = window.open(taskURL, "ExecutableURLService_Window");
}

Load Event Handler

$('a', this.context.element).text(linkText);

View Event Handler

$('a', this.context.element).click(function () {
    openTask(serviceID, taskInput);
});

In contrast to the all-in-one HTML string, determining what and how this custom CV functions is much easier as the supporting materials are organized and easier to read.

Note, to address a small issue with the anchor tag not showing the pointer on hover, we can also add this to the Inline CSS:

.scriptedLink {
    cursor: pointer;
}

Results:

ScriptedLinkCV.png 

The last column has a clickable link, while the one bound to the Output Text (onClick URL) does not due to the XSS sanitization:

ScriptedLinkCVInTable.pngAs an interesting side-effect, the target of the link is also hidden from users (no more displaying of the "javascript:void(0)" on hover), which may or may not be desirable.

Other Considerations

A custom CV doesn't need to be wholly generic, as it is designed for a specific purpose. However, if you know that there are similar use cases, then generalizing the components may be valuable. Think about how the data inputs, HTML structure, and scripting can be generalized to fit more of your use cases so you can get more mileage out of your custom control.

Protect your own controls from malicious users as well. Even though you may be working "around" the limitations imposed by the XSS protections in place with Brazos UI, you don't want to leave your own control open to exploitation. Unlike with an Output Text, which has the potential to display any arbitrary HTML, a custom control is likely to have a narrowly defined set of valid inputs. Make sure to use data validations and other defensive programming techniques to secure your own control.

Optimization of the control may be a concern when the control is used in numerous places on a single coach, including the copies resulting from use in repeating elements like a Table. For example, inline JS is replicated with each instance of the CV. Evaluate and balance the tidy encapsulation of the control against approaches that limit repetition, such as moving the JS definitions to the template-level or creating custom AMD modules. This is a consideration with any CV, however.

Have more questions? Submit a request

Comments

Powered by Zendesk