8

i'm wondering how safe it is to use createHTMLDocument to do HTML sanitization. I've tried to implement it like this:

function sanitize(string) {
  var elm = document.implementation.createHTMLDocument().body;
  elm.innerHTML = string;
  // traverse and filter elm to only allow whitelisted elements and attributes
  // e.g. use https://github.com/gbirke/Sanitize.js
  var cleaned_fragment = whitelist_filter(elm);
  elm = document.implementation.createHTMLDocument().body;
  elm.appendChild(cleaned_fragment);

  return elm.innerHTML;
}

It seems to work fine with all XSS attacks i've throw at it (no script evaluation or requests triggered). But I got a feeling it might be a bad idea, im I missing something?

I've created a jsfiddle if someone wants to experiment.

5
  • Are you trusting a client side javascript to sanitize the HTML? If I were an attacker, I'd simply bypass the sanitization completely by not calling your function. Sanitization has to be done server-side. Commented Feb 5, 2014 at 14:09
  • How would you bypass it? lets say this is a case where some client side javascript fetches from a server API that returns unsafe html that you would like to sanitize and insert into the page Commented Feb 5, 2014 at 14:24
  • 2
    @JohnDeters That depends very much on the context. Html encoding can happen on the client a web application where javascript weaves the data into the html for displaying on the same machine. You could bypass it, but that'd be like a script kiddy who proudly hacks 127.0.0.1. Commented Feb 5, 2014 at 15:02
  • In the case I mention wouldn't a bug in a sanitized be equally bad either if it's done server or client side? Commented Feb 5, 2014 at 15:05
  • Some libraries are made for that task, like DOMPurify. It use DOMParser, createHTMLDocument or toStaticHTML
    – mems
    Commented May 17, 2017 at 15:17

2 Answers 2

8

You should use the DOMParser to parse HTML when available, and only fall back to DOMImplementation.createHTMLDocument if the former is unavailable.

In Opera Presto, I observed network activity when I passed <img src=...> (but not <video>).
Internet Explorer 9- is worse: media, styles and event listeners will be activated with this method. IE10+ supports DOMParser, so if your audience uses IE10+, then you're safe.

3
  • Thanks, did know about DOMParser. Ok good to know, i noticed that Chrome tries to fetch img tags even when in a detached dom tree but does not if in a new document. Commented Feb 5, 2014 at 14:39
  • Did NOT know about* :) Commented Feb 5, 2014 at 16:49
  • 1
    @MattiasWadman If you don't mind loosing lots of potentially dangerous tags and attributes, you could also try the global toStaticHTML method in IE 8 + 9.
    – Rob W
    Commented Feb 5, 2014 at 16:54
2

Refering innerHTML of generated HTMLElement causes mXSS - a kind of DOM based XSS.

e.g, the code following causes mXSS at IE.

var s = "<listing>&lt;img src=1 onerror=alert(1)&gt;</listing>";
var parser = new DOMParser();
var doc = parser.parseFromString( s, "text/html" );
div.innerHTML = doc.body.innerHTML;

therefore, you have to manipulate as HTMLElement, don't refer innerHTML.

div.appendChild( doc.body.childNodes[ 0 ] );

see http://utf-8.jp/public/20140807/shibuyaxss.pdf and http://utf-8.jp/public/rickdom/

1
  • mXSS is really interesting and make you feel that html sanitize is a sad mess to deal with :) I guess server side sanitize is the only "sane" way but still really really hard and a never ending battle. Commented Sep 8, 2014 at 14:18

You must log in to answer this question.

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