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')
p.appendChild(document.createTextNode(message))
document.getElementById('chatbox').appendChild(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.