Chat webapp. Clients (that is, web browsers) send messages to the server, which the server broadcasts to all connected clients. Client-side code looks like this:

let p = document.createElement('p')

Where message is the string received from the server.

The problem here is that it is strongly recommended to sanitize server-side untrusted data before inserting it into document body, by removing special characters (<, >, ", etc) and replacing them with appropriate HTML entities. I was told the above code was vulnerable to XSS if this is not done.

However, such sanitization seems to lead to incorrect displaying of messages if document.createTextNode is used. Unlike innerHTML, document.createTextNode displays special characters verbatim and does not interpret them as HTML. Thus server-side sanitization that changes aforementioned characters to HTML entities will cause the clients to display the entities, not the characters the enities are supposed to represent.

As such I do not believe that such validation is necessary nor correct when document.createTextNode() is used.

However, I was told that it is nevertheless always necessary to sanitize untrusted strings server side. I was told that escaping these characters server-side was always necessary. In that case, am I supposed to stop using document.createTextNode() and start using innerHTML instead? That seems odd to me because I've always thought innerHTML to be one of the least secure features of JavaScript, which should not be used with untrusted content.

1 Answer 1


The input to createTextNode, textContent, and the non-standard innerText all take plain JavaScript strings. You do not need to and should not encode that input as HTML, plain JS strings are all you need.

That being said, you do still need to properly encode the message from the server. If you are outputting the text as HTML, you would encode it with HTML entities. If you are outputting the message as JavaScript or JSON, you would typically encode it with a JSON encoder. The correct encoding depends on the context it is output and is not always HTML.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .