Table of Contents

Best practices to avoid cross-site scripting (XSS) vulnerabilities

Pega Platform™ applications depend on JavaScript functions that are run in a web browser. As a result, application users potentially can be exposed to JavaScript-based cross-site scripting (XSS) security issues. Cross-site scripting is a client-side code injection attack, in which an attacker can run malicious scripts on a legitimate website or web application. If a malicious or infected site (or user) injects unauthorized JavaScript code into a browser form, execution of that JavaScript, on the same or another browser session, can cause serious security problems, including:

  • Hijacking the user session
  • Defacing websites
  • Introducing worms, bots, or viruses
  • Sending spam email

Many JavaScript functions are built into standard text file rules, HTML fragment rules, and HTML Property rules. Additional JavaScript files can be created as part of an application.

Pega Platform includes features and facilities that prevent many security vulnerabilities, and Pegasystems routinely tests for and analyzes potential security issues. However, the many software layers in use (network, email, application server, database, firewalls, and so on) make security an ongoing challenge. The practices described in this article address only one dimension of security, but one that has been heavily exploited when ignored.

Suggested approach

Pega recommends using the following best practices to protect against the most common ways that cross-site scripting (XSS) attacks gain access to a client browser:

These practices are always important whether or not your application:

  • Is used by unauthenticated users
  • Is exposed to a large community or embedded as a web mashup in other applications
  • Runs in a less-secure network
  • Runs in a less-secure physical environment
  • Includes stream rules that are not autogenerated

The best practices and the built-in features of Pega Platform are intended to help you build more secure applications by avoiding specific, well-known vulnerabilities.

Most guidance in this article applies to all Pega Platform applications. However, certain features as noted are available only in Pega Platform 5.3 SP1 and later versions.

Follow the guardrails

Follow the design and implementation guardrails described in Ten Guardrails to Success.

In a guardrail-compliant application, application rulesets contain only autogenerated flow actions, autogenerated sections, and autogenerated harness rules. The application might use standard rules that are not autogenerated.

Your application eliminates many potential security vulnerabilities, and is easier to maintain and document, by avoiding custom HTML, custom JavaScript, and custom Java.

Filter all inputs

Prevent invalid data from entering a work object or a work object attachment. Filter and validate input data as thoroughly as possible, including input that is submitted from browser forms, input from service requests (such as email), and input from connector responses. Do not rely on client-side editing, which is in the browser, because a hacker can easily bypass it. Perform validation in your server-side application logic.

Use the following features to validate individual values:

  • Property types – For Single Value, Value List, and Value Group properties, select the property type carefully. Use Integer, Double, Decimal, DateTime, Date, TimeofDay, and TrueFalse when appropriate. Rather than Text property type, use the Password or Identifier property type. Special characters that are common in JavaScript code (such as quotation marks), are never displayed in a numeric, date or time value, but might legitimately be displayed in Text, Password, or Identifier value.
  • Alllow lists – Several features let you constrain a property value to one of a fixed list or pattern of values, including the property table edits (local list, field values, class key values) on the General tab in Pega Platform 5.5 and later versions, or the Table Edit tab in earlier releases.
  • Restrictions – Complete the Max Length field for Text, Password or Identifier fields. For example, it is difficult to fit a malicious JavaScript program into a small number of characters.
  • Not declarative – If applicable, select the Cannot be a Declarative Target check box. This option is helpful, because a declarative expression could assemble JavaScript source code.
  • Special properties – Select the Cannot be included as an input field check box if the property is always computed from other values.
  • Validation – Identify an edit input rule and an edit validate rule when possible. Do not accept angle brackets, quotation marks, ampersands, or other special characters in fields unless necessary for a sound business reason. For example, the standard validation rule LetterorDigit limits values to only letters and digits. On the PRPC 5.5 property form, the Max Length and Validate fields are displayed on the Advanced tab.
  • Use map value rules, validation rules, and constraints rules to validate inputs.
  • To test arriving email attachments or other file attachments for software viruses and malicious JavaScripts, override the extension point activity Data-WorkAttach-File.CallVirusCheck with an activity that calls your third-party virus software. Your activity can call a Java class, or in a Microsoft Windows server, a Dynamic Linked Library routine.
  • Ensure that files that are uploaded from application user workstations and text files processed by a file listener are checked against viruses.
  • Input filtering is worthwhile even if an application has 100% coverage of output filtering for the HTML that the application sends to a browser. Applications often send output to other systems, rather than to a browser, which could contain a malicious JavaScript function, such as an HTML-rendered email message. Infecting another system, which might belong to another department, a customer, or to a supplier is a security failure that is no less serious than infecting an application user.
  • Avoid using the URL JavaServer Page (JSP) tag in manually created stream rules. If you must use a URL tag, call the SafeURL JavaScript functions to obfuscate the URL query string.

Filter HTML and XML outputs

Not all invalid data can be detected and 100% excluded during input processing. Some input fields legitimately and necessarily contain quotation mark characters, angle bracket characters, and other sensitive characters. For example, a user-entered text area on a form might contain a snippet of JavaScript or Java code that was entered to describe a software issue.

If invalid data, such as malicious JavaScript source code, somehow reaches a Pega Platform clipboard, applications that are built following the guardrails reduce the risk that the JavaScript code is ever sent to a browser in a form that can be executed.

Output from autogenerated harness, section, and flow action rules is automatically output-filtered. Application developers do not need a special approach for such rules. (This is applicable to Pega Platform 5.3 SP1 or later versions.)

In any non-autogenerated (manually created) stream rules (correspondence, paragraph rules, XML, HTML, flow actions, harness, or sections), use only Pega Platform JSP tags to ensure that output filtering occurs. Note these specific cases:

  • Even when you manually create only a portion of a full HTML or XML document, make the HTML code that your rules produce well-formed in terms of matching begin-end tags, matched quotation marks, use of only legitimate HTML tags, and correct nesting of tags. Various browser versions render malformed HTML in unpredictable ways, and some browsers become vulnerable to bugs and quirks after rendering malformed HTML code.
  • For the <pega:reference> or <p:r> tag, omit the mode attribute to provide complete XSS filtering. This is the default when your tag omits the mode attribute. Avoid mode=literal, which disables XSS filtering. Use mode=javascript when truly necessary, but with extreme care.
  • For the <pega:lookup> tag in PRPC 5.5 applications, avoid mode=literal. In versions prior to PRPC 5.5, the mode attribute is not available, and all uses of the <pega:lookup> tag provide XSS filtering.
  • Filter any potential-risk text value for XSS vulnerability using a Java scriptlet that calls one of two PublicAPI methods.

PublicAPI methods for XSS filtering

Output filtering involves replacing sensitive characters in the source HTML code such as angle brackets (< and >), single and double quotation marks, ampersands, and others by the equivalent HTML character entities, such as &lt; for < or &apos; for an apostrophe. If the source text is legitimate, output filtering does not prevent correct HTML rendering by the browser.

Use these two Java methods to provide output filtering:

  • StringUtils.crossScriptingFilter(aValue) – Filters the contents of aValue and returns a filtered (encoded) version. Available in PRPC 5.3 SP1 and later versions.
  • StringUtils.reversibleCrossScriptingFilter(aValue) – Filters the contents of aValue and reverse-filters the value in the server if the same value is resubmitted in subsequent requests. This method ensures that the friendly user’s intent is preserved. It was introduced in Pega Platform 5.5, and available in Pega Platform 5.3 SP1 and later versions through on-request hotfixes.

Use reversibleCrossScripting() when the internal clipboard value is not to be modified, but the value sent to the browser is to be filtered. For example, if an application user needs to search a customer master file for a customer named Molly O'Brian, the SQL statement (on the server) needs to process using the apostrophe (single quotation mark) character ('), but the browser display uses the HTML entity &apos; or an equivalent. In this case, a separate escape mechanism for SQL also applies, converting the name O'Brian to O\'Brian.

The following examples are portions of manually created stream rules that are modified to filter a value using these two PublicAPI functions in an inline Java scriptlet.

Example 1

Incorrect

 <%tools.appendString(tools.getActiveValue()); %>

Correct

 <%tools.appendString(StringUtils.crossScriptingFilter(tools.getActiveValue()));%>

or

 <%tools.appendString(StringUtils.reversibleCrossScriptingFilter(tools.getActiveValue()));%>

Example 2

Incorrect

 <%tools.appendString(tools.getSaveValue("savename”)); %>

Correct

 <pega:reference name=$save(savename) />

or

 <%tools.appendString(StringUtils.crossScriptingFilter(tools.getSaveValue("savename”))); %>

or

 <%tools.appendString(StringUtils.reversibleCrossScriptingFilter(tools.getSaveValue("savename”))); %>

Example 3

Incorrect

 <%tools.appendString(tools.getParamValue("paramname")); %>

Correct

 <pega:reference name=param.paramname/>

or

 <%tools.appendString(StringUtils.crossScriptingFilter(tools.getParamValue("paramname"))); %>

or

 <% tools.appendString(StringUtils.reversibleCrossScriptingFilter(tools.getParamValue("paramname"))); %>
Suggest Edit

100% found this useful

Have a question? Get answers now.

Visit the Collaboration Center to ask questions, engage in discussions, share ideas, and help others.