Salesforce Developer Security Xss


// Salesforce - Developer - Security - Cross Site Scripting:


As a platform, Salesforce offers its customers and developers maximum flexibility 
for accessing and storing data.  Were we to employ input filtering, we might strip 
out vital information from our customers' data against their wishes.  So, the 
Salesforce's approach to XSS defense is 100% output encoding.  We do not 
control what you place on our platform, but wherever possible, we make sure 
it is displayed securely.  In fact, by default, all merge fields are automatically 
HTML encoded.  For example:

<apex:outputText value="{!$CurrentPage.parameters.userName}"/>

is theoretically is vulnerable to XSS because user-supplied input is displayed.  
However, due to automatic HTML encoding, the platform change < and > into &lt; 
and &gt;.

While it is great that Salesforce automatically do HTML encoding out of the box, 
there are certain scenarios where you want to have raw HTML embedded in the 
page.  To disable automatic encoding, you need to set "escape" to false:

<apex:outputText escape="false">
  Hello {!$CurrentPage.parameters.userName}

While disabling encoding may be necessary for certain use cases, we should be 
extremely cautious.  If we disable automatic encoding, we have to rely on other 
XSS prevention technique (like whitelisting) to ensure that your code is not 
vulnerable to XSS attacks.

The platform automatically HTML encodes merge fields, but only in an HTML 
context, and auto-encoding only provide HTML encoding of <, >, and quotes 
within HTML attributes.  If your application passes through multiple parsing 
context, auto-encoding is not fully sufficient.  For example,

<div onclick="console.log('{! $CurrentPage.parameters.userInput}')">
  Click me!</div>

the userInput is rendered with a JavaScript execution context embedded within 
an HTML context, and therefore auto-HTML encoding alone is not sufficient.

When inserting merge fields into JavaScript, watch out for XSS vulnerables. Take 
a look at this example:

  var x = '{! $CurrentPage.parameters.userInput}'; // vulnerable to XSS

Here, user input is inserted into script context, so the value is not automatically 
encoded and is vulnerable to XSS.

Modern browsers do not allow JavaScript injection within CSS attribute values.  
However, some older browsers do.  Be careful with using merge field within 
a style context:

  .foo {
    color: #{! CurrentPage.parameters.userInput}; // vulnerable to XSS

In the above code, the default automatic HTML encoding is not applied, and the 
application is vulnerable to XSS attacks.

While protects developers from XSS in some basic use cases, there 
are cases (<script> tags, <style> tags, and action handlers, for example) where 
developers need to do their own encoding to make sure that their application 
are not vulnerable.

<apex:outputText value="{!sampleMergeField}"/> // vulnerable: NO 
<apex:outputText value="{!sampleMergeField}" escape="false"/> // vulnerable:YES
<apex:outputText>{!sampleMergeField}</apex:outputText> // vulnerable: NO ?
{!sampleMergeField} // vulnerable: NO


  var x = '{! $CurrentPage.parameters.userInput}'

The above code is vulnerable to XSS attacks.  Consider if the user input is something 

userInput'; alert(1); //

This causes the application to produces:

  var x = 'userInput'; alert(1); //';

To ensure that unsafe characters are properly encoded, we have to wrap the merge 
field with the JSENCODE function:

  var x = '{! JSENCODE($CurrentPage.parameters.userInput)}';

JSINHTMLENCODE is a legacy Visualforce function that was introduced when the 
platform did not always automatically HTML encode merge-fields.  JSINHTMLENCODE 
is effectively a combination of HTMLENCODE(JSENCODE()), so before the introduction 
of auto-HTML encoding, developers called this function when including merge-fields 
in JavaScript event handlers within HTML (that is, onerror, onload, onmouseover, 
etc).  Now that the platform auto-HTML encodes, it is sufficient to just call 

Up until now, we've focused completely on preventing XSS by modifying our 
Visualforce pages.  What can we do if we need to encode in Apex?  Encoding within 
controller is strongly discouraged.  We should always encode as close to the rendering 
context as much as possible (for example, in Visualforce).  Whenever encoding 
occurs within a controller, a dependency is created between the view and the 
controller, whereas the controller should be agnostic to how the data is rendered.  
Furthermore, this pattern is not robust because the Visualforce page may want to 
render the same variable in several different contexts, but the controller can only 
encode once.  Nevertheless, we may need to encode within the controller. For 
example, if we are generating dynamic HTML from within our controller.  To do so, 
anything under the control of a user requires encoding to prevent special characters 
from being interpreted as code instead of text.  Salesforce provides various Apex 
encoding functions through the ESAPI which exports global static methods 
that we can use in our package to perform security encoding.  This package can be 
installed in any Salesforce org as an unmanaged package.  To use the ESAPI:


The platform provides two main mechanisms to avoid cross site scripting: auto 
HTML encoding as well as built in encoding functions that can be invoked 
manually from VisualForce. Nevertheless in order to use these protections 
correctly, the developer needs to have a thorough understanding of how user 
controlled variables are rendered by the browser.

Built in Auto Encoding:

All merge-fields are always auto HTML encoded provided they

1. do not occur within a <style> or <script> tag

2. do not occur within an apex tag with the escape='false' attribute

The auto HTML encoding performed is applied last (after any other VisualForce 
functions) and is applied regardless of whether you use any other VisualForce 
encoding functions. It does not matter whether the merge-field is rendered via 
an explicit apex tag or directly using the braces notation within HTML markup. 
Your application code needs to take auto-encoding into account in order to 
avoid double encoding or improperly encoding merge-fields.

For example, the value of the userInput parameter will be HTML encoded in the 

  {!$CurrentPage.parameters.userInput} <!-- safe (auto HTML Encoded) -->

or here:

  {!$CurrentPage.parameters.userInput} <!--safe (auto HTML Encoded) -->

But no auto-encoding is performed here because of the script tag:

  var x = '{!$CurrentPage.parameters.userInput}'; //vulnerable to XSS

And no auto-encoding is performed here because of the style tag:

  .foo {
    color: #{!$CurrentPage.parameters.userInput}; //vulnerable to XSS

The auto encoding only provides HTML Encoding of <, > and quotes within html 
attributes. You must perform your own Javascript and URL encoding as well as 
handle CSS cross site scripting issues.

Auto-HTML encoding is not sufficient when passing through multiple parsing 

<!--vulnerable to XSS -->
<div onclick = "console.log('{!$CurrentPage.parameters.userInput}')">
Click me!</div> 

In the above code fragment, userInput is rendered with a Javascript execution 
context embedded with an HTML context, and so the auto-HTML encoding is 
insufficient. For these and other uses cases, the platform provides VisualForce 
encoding functions that can be chained together to provide sufficient encoding 
in multiple contexts.

In the above code fragment, userInput is rendered with a Javascript execution 
context embedded with an HTML context, and so the auto-HTML encoding is 
insufficient. For these and other uses cases, the platform provides VisualForce 
encoding functions that can be chained together to provide sufficient encoding 
in multiple contexts.

1. url: Can contain arbitrary text. The platform will prepend the url with 
   'http://' if no scheme is provided.

2. picklist: Can contain arbitrary text, independent of the field definition. 
   Picklist values are not enforced by the schema, and users can modify a 
   picklist value to contain any text via an update call.

3. text: can contain arbitrary text

4. textarea: can contain arbitrary text

5. rich text field: Allows a whitelist of HTML tags, and all other HTML 
   characters are HTML-encoded. Safe to use unencoded in an HTML rendering 
   context but not in any other rendering context (e.g. javascript control 
   characters are not encoded).

Name fields can be arbitrary text, and must be considered unsafe. This also 
applies to global variables such usernames.

Built in VisualForce encoding functions:

1. JSENCODE: performs string encoding within a Javascript String context

2. HTMLENCODE: encodes all characters with the appropriate HTML character 
   references so as to avoid interpretation of characters as markup.

3. URLENCODE: performs URI encoding (% style encoding) within a URL component 

4. JSINHTMLENCODE: a convenience method that is equivalent to the composition 

Because the parsing flow is HTML Parser -> JS Parser, the mergefield must be 
properly encoded as: HTMLENCODE(JSENCODE(x)). As we know that the platform will 
HTML auto-encode last, it is enough to explicitly invoke the inner encoding, 

What is the merge-field is not typed as a string? One option is to leave the 
merge-field naked. However this is a dangerous anti-pattern because it creates 
a dependency between the implementation details in the controller and the 
security of the visualforce page. Suppose, for example, that in the future, 
the controller pulls this value from a URL parameter or textfield. Now the 
visualforce page is vulnerable to cross site scripting. The security of the 
visualforce page should be decoupled as much as possible from the controller 

Therefore we recommend defensive programming -- cast to the appropriate type 
explicitly using the built in constructors:

  var myint = parseInt("{!JSENCODE(int_data)}"); 
  //now we are sure that x is an int

  var myfloat = parseFloat("{!JSENCODE(float_data)}");  
  //now we are sure that y is a float

  var mybool = {!IF(bool_data, "true", "false")};  
  //now we are sure that mybool is a boolean

  var myJSON = JSON.parse("{!JSENCODE(stringified_value)}"); 
  //when transmitting stringified JSON

This way a subtle change in the controller implementation (for example, pulling 
the value from a URL parameter or text field) will not trigger a security 
vulnerability in the corrspondong VisualForce page.

HTMLENCODE is required when userdata is interpreted in an HTML Context and is 
not already auto-encoded.  For example:

<apex:outputText escape="false" 
  value="<i>Hello {!HTMLENCODE(Account.Name)}</i>" />

In the above, because Name fields can be arbitrary text strings, any rendering 
of this field needs to be properly output encoded. Because we want to combine 
markup (italics) with data, the apex tag is set to escape="false" and we 
manually encode user data.

As always, one layer of encoding needs to be applied for each layer of parsing:

<div id="foo"></div>
  document.querySelector('#foo').innerHTML='Howdy ' + 

In the above, the merge-field first passes through the HTML Parser when the 
page is loaded, but because the merge-field is within a script tag, the HTML 
parser does not perform character reference substitution and instead passes the 
contents of the script block to the javascript parser. Javascript code then 
calls innerHTML which performs HTML parsing (and character reference 
substitution). Therefore the parsing is Javascript -> HTML, and the necessary 
encoding is JSENCODE(HTMLENCODE()). Note that only performing JSENCODE or only 
performing HTMLENCODE will lead to a broken page and possibly a cross site 
scripting vulnerability.

Consider the following example:

<div onclick="this.innerHTML='Howdy {!Account.Name}'">Click me!</div>

Here, the merge-field is sent through the HTML parser when the page is loaded. 
Because it is not in a script or style tag, character reference substitution 
occurs, and the result is then sent to the Javascript decoder (in the definition 
of the onclick event handler). Once clicked, the result will be sent back to 
the HTML parser for innerHTML rendering. Therefore there are three layers of 
decoding: HTML -> Javascript -> HTML, and as a result, three layers of encoding 
need to be applied. However HTML auto encoding will be automatically applied at 
the outer layer, so the developer needs to only apply JSENCODE(HTMLENCODE()):

<!-- safe -->
<div onclick="this.innerHTML='Howdy {!JSENCODE(HTMLENCODE(Account.Name))}'">
  Click me!</div>


<!-- vulnerable to XSS -->
<div onclick="this.innerHTML='\x3cdiv onclick=\x22console.log(\x27Howdy 
 {!Account.Name}\x27);\x22\x3eClick me again!\x3c/div\x3e'">Click me!</div>

Here, the merge-field is first parsed by the HTML parser when the page is 
loaded, is then passed to the Javascript parser in the definition of the 
on-click handler, is passed again to the HTML parser when the onclick handler is 
invoked, and is finally passed to the Javacript parser when the element is 
clicked a second time. Therefore the merge-field needs to be encoded as follows: 


Because auto-encoding takes care of the outer HTMLENCODE, the code fragment can 
be properly sanitized as follows:

<!-- safe -->
<div onclick="this.innerHTML='\x3cdiv onclick=\x22console.log(\x27Howdy 
 \x22\x3eClick me again!\x3c/div\x3e'">Click me!</div>

URLENCODING maps each character with ascii code 00-255 to the corresponding two 
byte hex representation as %XX. Therefore URLENCODING will not provide valid 
absolute URLs and should only be used when encoding URI components:

<!-- Safe -->
<img src="/foo?name={!URLENCODE(}">{!Pic.Name}</img>

In the above fragment, Pic.Name within the text content of the image tag does 
not need to be encoded because it will be auto HTML encoded). Because 
URLENCODING has such a restricted character output, there is no need to do any 
additional encoding once URLEncoding is applied, as %XX is not a valid control 
character for any of the other parsing contexts. Therefore the following is 
safe and does not need any JSENCODING or HTMLENCODING:

<!-- Safe, but anti-pattern -->
  var x = '{!URLENCODE(}';
  var el = document.querySelector('#foo');
  el.outerHTML = '<img src = "/pics?name=' + x + '">';

Nevertheless, even though the above code is safe, it is recommended that you 
minimize use of HTML rendering as much as possible:

  <!-- Safe, and no use of HTML rendering -->
  var x = '{!URLENCODE(}';
  var el = document.querySelector('#foo');
  el.src = '/pics?name=' + x;

One thing to keep in mind about URLs is that all browsers will accept a 
javascript pseudo-scheme for location URLs while older browsers will also 
accept a javascript pseudo-scheme for src attributes or url attributes within 
CSS. Therefore you must control the scheme as well as the host and only allow 
user input to set URL parameters or paths. In those cases when users select the 
host, you must whitelist the set of allowed hosts and validate this whitelist 
to avoid arbitrary redirect vulnerabilities.

JSINHTMLENCODE is a legacy VisualForce function that was introduced when the 
platform did not always auto HTML encode merge-fields. JSINHTMLENCODE is 
effectively a combination of HTMLENCODE(JSENCODE()), so before the introduction 
of auto-HTML encoding, developers would need to call this function when 
including merge-fields in javascript event handlers within HTML. Now that the 
platform auto-HTML encodes, it is sufficient to call JSENCODE() in this case.

<!-- safe, but broken due to double html encoding -->
<div onclick="console.log('{!JSINHTMLENCODE(Account.Name)}')">Click me!</div>

<!-- safe and accurate -->
<div onclick="console.log('{!JSENCODE(Account.Name)}')">Click me!</div>

However, because the set of control characters for HTML and Javascript is almost 
disjoint, calling JSINHTMLENCODE can still be used as a replacement for 
JSENCODE(HTMLENCODE(x)), and can therefore save one function call in 

  var el = document.querySelector('#foo');
  el.innerHTML = "Howdy {!JSINHTMLENCODE(Account.Name)}"; //safe and accurate

// XSS in CSS:

Cascading Style Sheets is an increasingly complex language that is only slowly 
becoming standardized across browsers. All modern browsers do not allow 
javascript injection within CSS attribute values, however this is not true for 
older browsers. Unfortunately it is not sufficient to cast CSS attribute values 
to strings and then encode the values because many CSS properties are not 
rendered as strings.

<!-- vulnerable to XSS unless whitelisted in controller-->
foo {
  color: #{!color};

As a result, do not place any merge-fields within a <style> tag unless they are 
either whitelisted in the controller. Alternately, first pass the variables to 
a javascript context, validate them in javascript, and then use CSSOM or a js 
toolkit to update the style programmatically:

var el = document.querySelector('#foo');
var color = '{!JSENCODE(color)}'; //must JSENCODE to prevent breakint out 
  // of string
if ( /(^[0-9a-f]{6}$)|(^[0-9a-f]{3}$)/i.test(color) ) {'#' + color; //safe to render into a style context

Note that no auto-html encoding is done by the platform when the DOM is 
rendered client-side.

Consider the following streaming API example:

//vulnerable code
cometd.subscribe('/topic/foo', function(message) {
  var data = document.createElement(‘li’);
  data.innerHTML = JSON.stringify(;

Here if foo__c is built from one of the dangerous sObject types such as text, 
passing it to an html rendering function creates a vulnerability. In this case, 
the developer has two options:

1. Use a safe DOM manipulation function such as innerText, rather than innerHTML

2. Properly encode the data in javascript prior to the innerHTML write

The first option is preferred, but may sometimes be impractical (for example 
when you are using a higher level toolkit that performs innerHTML writes in the 
method you are using.) In this case you must use a javascript encoding library.

Although Salesforce does not currently export javascript security encoding 
methods, there are a number of third party security libraries that you can use.

We recommend the Go Instant secure-filters library ( 
because  it has been vetted by the Salesforce security team and is small and 
easy to use. It is also available as a node package. To use this library, place 
the secure-filters.js file in your static resources. The library will export a 
secureFilters object which has a number of encoding methods: built-in API encodings:

Javascript remoting can be invoked with {escape: false} or (the default) 
{escape: true}. Enabling escaping means that the response is html encoded. In 
general developers should use {escape: true} when possible, but there are many 
cases where global html encoding at the transport layer is inappropriate.

1. Encoding at the transport layer means that every field is html encoded, 
   even if some fields (e.g. rich text fields) should not be encoded.

2. In some cases, built in encoding is not available at the transport layer.

However, the advantage of html encoding at the transport layer is that if your 
page design is very simple (so that you only need html encoding), then you will 
not need to import a client side encoding library.  The following table lists 
the transport-layer encoding policies of different APIs:

1. SOAP API/REST API: never encode
2. Streaming API: never encode
3. Ajax Toolkit: never encode
4. Javascript Remoting: HTML encoding unless explicit {escape: 'false'}
5. Visualforce Object Remoting: always HTML encodes

If you are using a higher level API (such as the REST Toolkit or Mobile Toolkit), 
please examine the documentation to determine what the encoding policies are, 
or examine the code to determine which low level APIs are being invoked. For 
example, the ForceTk client uses the REST API, and therefore all data is passed 
back raw.

Other taint sources:

In addition to API calls, taint can be introduced into the page through a 
number of browser supplied environment variables such as location, cookie, 
referer, window.Name, and local storage -- as well as through data pulled from 
any other remote source (e.g. window.postMessage, xhr calls, and jsonp). 
Finally, taint sources can propage through other DOM properties.

Developers still need to be mindful of the type of data that is passed into the 
framework and the ultimate context in which the data will be rendered in order 
to properly output encode all variables, but additionally they need to study the 
built in encoding options offered by the framework. Generally all frameworks 
have support for some kind of html encoding, but the developer should verify 
that this includes escaping of single and double quotes for rendering within 
html attributes.

For rendering URLs, Javascript, or CSS, the developer is on their own and must 
either not render user-data in these contexts or use a third party security 
library to properly escape output in all contexts other than pure html.

One concern to keep in mind is that sometimes template data is stored in 
textarea tags with visibility set to hidden. In this case, be aware that HTML 
rendering occurs when data is sent to a textarea field.

Finally, never place merge-fields into template data, as templates are invoked 
with eval(). Rather, define use merge-fields to define variables outside of 
your template and then pass the variable reference to the template.

Underscore Templates:

All templates use innerHTML style rendering and so developers must ensure that 
template variables are encoded. Underscore templates allow for auto-HTML 
encoding with the <%- %>. No HTML encoding is done with <%= %>, which should in 
general be avoided. However, HTML encoding is generally insufficient so these 
templates cannot be securely used for templating unless you include additional 
client side encoding functions. The following example shows how to secure an 
underscore_js tempalate using the secure-filters library.

// ESAPI and Encoding within Apex:

Encoding within the controller is strongly discouraged as you should encode as 
close to the rendering context as possible. Whenever encoding occurs within a 
controller, a dependency is created between the View and the Controller, whereas 
the controller should be agnostic to how the data is rendered. Moreover, this 
pattern is not robust because the visualforce page may want to render the same 
variable in several different contexts, but the controller can only encode in 

Do not attempt to generate HTML code or javascript code in the controller.

Nevertheless if you must encode within the controller, please use the latest 
version of the ESAPI, which exports global static methods that can be 
used in your package to perform security encoding.

String usertext = ApexPages.currentPage().getParameters().get('usertext');
// the next line encodes the usertext similar to the VisualForce 
// HTMLENCODE function but within an Apex class.
usertext = ESAPI.encoder().SFDC_HTMLENCODE(usertext);

Do not use the built in Apex String Encoding functions: 
String.escapeEcmaScript(), String.escapeHtml3() and String.escapeHtml4(). These 
functions are based on Apache's StringEscapeUtils package which was not designed 
for security encoding and should not be used.

// Dangerous Programming Constructs:

S-Controls and Custom JavaScript Sources:

The apex:includeScript> Visualforce component allows you to include a custom 
script on the page. In these cases be very careful to validate that the content 
is sanitized and does not include user-supplied data. For example, the 
following snippet is extremely vulnerable as it is including user-supplied input 
as the value of the script text. The value provided by the tag is a URL to the 
JavaScript to include. If an attacker can supply arbitrary data to this 
parameter (as in the example below), they can potentially direct the victim to 
include any JavaScript file from any other web site.

<apex:includeScript value="{!$CurrentPage.parameters.userInput}" />

S-Control Template and Formula Tags:

S-Controls give the developer direct access to the HTML page itself and includes 
an array of tags that can be used to insert data into the pages. S-Controls do 
not use any built-in XSS protections. When using the template and formula tags, 
all output is unfiltered and must be validated by the developer.  The general 
syntax of these tags is: {!FUNCTION()} or {!$OBJECT.ATTRIBUTE}.

For example, if a developer wanted to include a user’s session ID and in a link, 
they could create the link using the following syntax:

<a href="{!$Api.Session_ID}&
  server={!$Api.Partner_Server_URL_130}”>Go to portal</a>

Which would render output similar to:

<a href=" sid=4f0900D30&
to portal</a>

Formula expressions can be function calls or include information about platform 
objects, a user’s environment, system environment, and the request environment. 
An important feature of these expressions is that data is not escaped during 
rendering. Since expressions are rendered on the server, it is not possible to 
escape rendered data on the client using JavaScript or other client-side 
technology. This can lead to potentially dangerous situations if the formula 
expression references non-system data (i.e. potentially hostile or editable) 
and the expression itself is not wrapped in a function to escape the output 
during rendering. A common vulnerability is created by the use of the 
{!$Request.*} expression to access request parameters:

    Hello world!

This will cause the server to pull the title parameter from the request and 
embed it into the page. So, the request:

would produce the rendered output

    Hello world!

Unfortunately, the unescaped {!$Request.title} tag also results in a cross-site 
scripting vulnerability. For example, the request:

results in the output:


The standard mechanism to do server-side escaping is through the use of the 
SUBSTITUTE formula tag. Given the placement of the {!$Request.*} expression in 
the example, the above attack could be prevented by using the following nested 

   Hello world!

Depending on the placement of the tag and usage of the data, both the characters 
needing escaping as well as their escaped counterparts may vary. For instance, 
this statement:

<script>var ret = "{!$Request.retURL}";</script>

would require that the double quote character be escaped with its URL encoded 
equivalent of %22 instead of the HTML escaped ", since it’s likely going to be 
used in a link. Otherwise, the request:'xss')%3B%2F%2F

would result in:

<script>var ret = "foo";alert('xss');//”;</script>

Additionally, the ret variable may need additional client-side escaping later in 
the page if it is used in a way which may cause included HTML control characters 
to be interpreted. Examples of correct usage are below:

     // Encode for URL
     var ret = "{!URLENCODE($Request.retURL)}";
     window.location.href = ret;

     // Encode for JS variable that is later used in HTML operation
     var title = "{!JSINHTMLENCODE($Request.title)}";
     document.getElementById('titleHeader').innerHTML = title;

     // Standard JSENCODE to embed in JS variable not later used in HTML
     var pageNum = parseInt("{!JSENCODE($Request.PageNumber)}");

Formula tags can also be used to include platform object data. Although the data 
is taken directly from the user’s org, it must still be escaped before use to 
prevent users from executing code in the context of other users (potentially 
those with higher privilege levels.) While these types of attacks would need to 
be performed by users within the same organization, they would undermine the 
organization’s user roles and reduce the integrity of auditing records. 
Additionally, many organizations contain data which has been imported from 
external sources, which may not have been screened for malicious content.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License