I have unescaped data from users.
So is it safe to use like this:
var data = '<test>a&f"#</test>'; // example data from ajax response
if (typeof(data) === 'string')
$('body').text(data);
Can I use like this or there is some problems like encoding or some specific symbols that I should be careful and add more strict validation?
When you set the text of an element using the text
method, jQuery uses createTextNode
internally, which escapes all special characters.
From the jQuery docs:
We need to be aware that this method escapes the string provided as
necessary so that it will render correctly in HTML. To do so, it calls
the DOM method .createTextNode()
, which replaces special characters
with their HTML entity equivalents (such as <
for <
)
So yes, it should be safe. Here's your example in jsfiddle. Notice how the tags appear as literal text.
Because XSS attacks rely on being able to insert DOM nodes (<img />
, <script />
) etc, and jQuery.fn.text()
does not support this, it is entirely XSS safe.
As you can see in this basic example, all would-be-HTML tags are encoded as a result of jQuery using createTextNode
internally:
jQuery('div').text('<test>a&f"#</test>');
So that what is actually inserted is more equivilant to;
jQuery('div').html('<test>a&f"#</test>');
You still have to be careful when inserting the result into the DOM - see: Cross-Site Scripting vulnerability with JavaScript and JQuery.
For setting the text of elements, however, text should be XSS safe.
The author from http://benv.ca/2012/10/02/you-are-probably-misusing-DOM-text-methods/ argues against using createTextNode
or jQuery's .text()
.
...if you know the context in which you are injecting the value (i.e. not attributes), then this method is safe. My argument is that developers don’t understand those contexts well enough, and sooner or later they will get it wrong.
It is better to use string replacement (of at least <
).
Some examples from well-secured libraries:
- Mustache https://github.com/janl/mustache.js/blob/master/mustache.js#L55
- Angular https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L438
The #1 OWASP suggestion is:
RULE #1 - HTML Escape Before Inserting Untrusted Data into HTML Element Content
Unlike the .html() method, .text() can be used in both XML and HTML
documents. The result of the .text() method is a string containing the
combined text of all matched elements. (Due to variations in the HTML
parsers in different browsers, the text returned may vary in newlines
and other white space.)
.text(data)
would strip the <test></test>
away and leave you with a&f#
Yes. It deals in text, not code.