I want to be 100% secure, I create raw html this way:

const template = document.createElement('template')
template.innerHTML = html_raw
const cloned = template.content.cloneNode(true)


When I build the html I insert independently every string to his respective html element (from json data object) who pass the validation function

In the validation function, I white list this characters: a-z0123456789(),.:-_/@%'space obviously a space is

after validate the string I replace this characters (),.:-_/@%'space to HTML encoding, for example ( equal to (

my question is, is secure HTML encoding in this way, inserting via innerHTML from html_raw related to HTML context (xss attack)?

I saw this question about innerHTML script can not be executed: https://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml

I bypass innerHTML with: <img src="" onerror=alert(0)> but if I replace with HTML encoding: &lt;img src=&quot;&quot; onerror=alert(0)&gt; does not execute the script

1 Answer 1


If you want to insert untrusted HTML markup as text, then you should use the textContent property, not innerHTML. The textContent property reliably prevents XSS attacks, because the content is only rendered as text and never interpreted as HTML markup, regardless of special characters like < and >.

Trying to come up with your own HTML filters is generally a bad idea, because there's a huge risk of getting this wrong. In your example, you show that angled brackets and double quotes are converted into HTML entities, but your list does not include those characters -- so that's already a mistake either in your list or your description.

If you want to be sure, use the (correct) features provided by the browser itself.

  • 1
    Hi, I already used textContent inside the build html, I think you can not escape single quota with textContent, do you know another way to insert raw html securely ?, because textContent is for text. By the way I have a whitelist no Blacklist so -- does not matter. Mar 22 at 20:28
  • you might look into using a sandboxed iframe: w3schools.com/tags/att_iframe_sandbox.asp Mar 22 at 21:13
  • @Thenothing: You say you already use textContent when you build HTML elements (with JavaScript, obviously). Then you shouldn't need innerHTML at all. Building HTML with JavaScript means you get Node objects which can be inserted directly into the document through methods like Node.appendChild(). The innerHTML is only required if you have a string with HTML markup (typically from the server). You don't have to escape anything with textContent, because all characters (including single quotes) are treated as literal text and not interpreted as HTML markup.
    – Ja1024
    Mar 22 at 23:12
  • @Thenothing: It does matter whether or not your whitelist is complete. If it's incomplete, you're blocking characters which shouldn't be blocked. This may not lead to XSS vulnerabilities, but it's a bug which can definitely cause problems.
    – Ja1024
    Mar 22 at 23:15
  • @browsermator: I'm not sure what this has to do with the question.
    – Ja1024
    Mar 22 at 23:15

You must log in to answer this question.

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