Apparently, this is harder to find than I thought it would be. And it even is so simple...
Is there a function equivalent to PHP\'s htmlspecialchars built into Javas
Underscore.js provides a function for this:
_.escape(string)
Escapes a string for insertion into HTML, replacing &, <, >, ", and ' characters.
http://underscorejs.org/#escape
It's not a built-in Javascript function, but if you are already using Underscore it is a better alternative than writing your own function if your strings to convert are not too large.
With jQuery it can be like this:
var escapedValue = $('<div/>').text(value).html();
From related question Escaping HTML strings with jQuery
As mentioned in comment double quotes and single quotes are left as-is for this implementation. That means this solution should not be used if you need to make element attribute as a raw html string.
Hope this wins the race due to its performance and most important not a chained logic using .replace('&','&').replace('<','<')...
var mapObj = {
'&':"&",
'<':"<",
'>':">",
'"':""",
'\'':"'"
};
var re = new RegExp(Object.keys(mapObj).join("|"),"gi");
function escapeHtml(str)
{
return str.replace(re, function(matched)
{
return mapObj[matched.toLowerCase()];
});
}
console.log('<script type="text/javascript">alert('Hello World');</script>');
console.log(escapeHtml('<script type="text/javascript">alert('Hello World');</script>'));
OWASP recommends that "[e]xcept for alphanumeric characters, [you should] escape all characters with ASCII values less than 256 with the &#xHH;
format (or a named entity if available) to prevent switching out of [an] attribute."
So here's a function that does that, with a usage example:
function escapeHTML(unsafe) {
return unsafe.replace(
/[\u0000-\u002F]|[\u003A-\u0040]|[\u005B-\u00FF]/g,
c => '&#' + ('000' + c.charCodeAt(0)).substr(-4, 4) + ';'
)
}
document.querySelector('div').innerHTML =
'<span class=' +
escapeHTML('this should break it! " | / % * + , - / ; < = > ^') +
'>' +
escapeHTML('<script>alert("inspect the attributes")\u003C/script>') +
'</span>'
<div></div>
Disclaimer: You should verify the entity ranges I have provided to validate the safety yourself.