You need to feed vaild json data into JSON parse functions. Typically whatever creates the json string needs to create valid json and therefore that's what needs to escape the html (and other) characters.
And if you google, 'how to escape json' you'll get a lot of sites which show how to do it halfway.
Most will point out a small group of chars and say do this:
\b Backspace (ascii code 08)
\f Form feed (ascii code 0C)
\n New line
\r Carriage return
\t Tab
\v Vertical tab
\' Apostrophe or single quote
\" Double quote
\\ Backslash caracter
This is partially correct. You need to escape:
- quotation mark (U+0022)
- reverse solidus (U+005C)
control characters U+0000 to U+001
which is everything below ascii32 (space)see: http://la.remifa.so/unicode/unicode.php?start=0000&end=007F
These characters get escaped by using \u + hexadecimal ie. "\u002F"
Here's the spec: http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
Personally, I only use the \u-hex notation for all escape sequences and I never worry about if the json might be used inside of the JavaScript context.
Json and Javascript are pretty cool in that you could escape every char as \u+hex if you wanted which makes XXS pretty much impossible (especially when inside of double quotes).
Update:
Keep in mind escaping the json is only 1 part of a complete XSS safe site. You still need to worry about how the json string might be used, as it could be passed into a function as an argument or you might create an array with the data or you might place the string inside of an document.getElementById('xyz').innerHTML(json.data)
So if the json data stays in the javascript context, you're safe to use \u+hex escaping.
When the string is moving into the html context, you need to treat it as html:
document.getElementById('xyz').innerHTML(json.data) //oh-no: now it will in html context
So you need to convert the JSON data with a function like this:
var __entityMap = {
"&": "&",
"<": "<",
">": ">",
'"': '"',
"'": ''',
"/": '/'
};
String.prototype.toHtml = function() {
return String(this).replace(/[&<>"'\/]/g, function (s) {
return __entityMap[s];
});
}
So now you can do this:
document.getElementById('xyz').innerHTML(json.data.toHtml() ) //ok -- now safe for html