Calling JSON.stringify
on any valid JS object is always safe, as is passing the result of that call to JSON.parse
. Stringification will automatically escape any characters that need it; no need to do so manually. Therefore, one way to do this safely (if overcautiously) is the following:
let msg = 'For input string: ' + request.UserInput;
let input = {"id": "34245425", "field": false, "information": [{"message": nullmsg}]};
input.information[0].message = 'For input string: ' + request.UserInput;
let inputStr = JSON.stringify(input);
This is always going to be safe, because you're not mixing things that are strings (the value 'For input string: ', the user content) with things that aren't (JSON or the object itself); you build a string, and then use the language features to add it to the object and built-in APIs to convert that object to (and presumably later from) a JSON string. It is safe to combine the first two lines into one, ... "information": [{"message": "For input string: " + request.UserInput}]};
because the JS parser will still evaluate the string concatenation expression before assigning it to the message
property, but I spread it out for clarity. This one is safe to do anything with.
- Remove the seemingly-redundant "For user input: " so the second line of the block above just becomes
input.information[0].message = request.UserInput;
and the first line goes away entirely. - Nest the message subfields in their own objects, so it becomesthe first two lines become
input.information[0].message = {"inputString": request.UserInput};
or similar.
As a general rule, if you find yourself trying to write an XSS filter, or indeed any kind of sanitizer for a common format, you're doing at least one thing wrong. It might just be "not using a common, well-tested library", but it's reasonably likely to be "not using language or framework features that render the whole question moot" or "using a design where this is even necessary".
EDIT: Clarified the code examples to highlight the over-cautious approach