• Interesting article.  If you are the author, I have one suggestion: prior to this, I didn't know there was a proposed browser API for HTML sanitization, so I was kind of confused about what the point of the article was.  Some context early in the article would be helpful.

  • My big gripe is there's no way to exclude tags from set HTML. It's all or nothing with unsafe. Say you want to allow locked down iframes in your html. Well, now you have to use unsafe and re add all the potentially risky tags and attributes and maintain that list forever because you can't derive from a default safe sanitizer.

    Well, now you have to use unsafe

    The article only briefly mentions it, but there is a second argument to .setHTML that allows you to pass a custom sanitizer.

    and re add all the potentially risky tags and attributes and maintain that list forever because you can't derive from a default safe sanitizer.

    And the constructor by default extends the safe sanitizer so this just works:

    const sanitizer = new Sanitizer();
    sanitizer.allowElement({ name: "iframe", attributes: [{ name: "src" }] });
    content.setHTML(untrusted, { sanitizer });
    

    You have to use the unsafe method - you cannot allow elements blocked by setHTML - they are always blocked:

    The method removes any elements and attributes that are considered XSS-unsafe, even if allowed by a passed sanitizer. Notably, the following elements are always removed: <script>, <frame>, <iframe>, <embed>, <object>, <use>, and event handler attributes.

    Edit: relevant portion of the spec here

    You have to use the unsafe method - you cannot allow elements blocked by setHTML - they are always blocked:

    So I read the text more, and yes it appears you're correct that .setHTML always forces XSS protection on, though it seems like setHTMLUnsafe also accepts a sanitizer and won't force the XSS protection, so you can just do:

    content.setHTMLUnsafe(untrusted, { sanitizer });
    

    (Note that new Sanitizer() still inherits the default config, so this means you can just add elements you need to the whitelist like above).

    Oh huh, the defaults WERE added after all! I don't think the MDN docs make that very clear that this is possible on some of the docs pages, may add it. Thanks! I do wish it allowed for more more intelligence (callback based, for example), but still a very good step forward!

    This seems extremely niche - in this case you could just use the safe method to do every else and then just replace the iframes afterwards I suppose? Having a fragment of HTML with multiple iframes in it you want to inject in one go sounds like a very unusual scenario.

    iframes are actually able to be made very secure - in fact, they're the preferred way to load user plugins as you can sandbox them pretty tightly. For example, it'd allow you to, for example, allow embedding content (like YT) while placing restrictions on what those iframes can do.

    I'm not arguing against that, I'm arguing you wouldn't often want to use this API to try and drop in complex HTML fragments containing multiple iframes in one go. So you could just do the safe setup of your page layout and then use innerHTML just to set up the iframes if you need to do that.

    Very quite literally at the VERY TOP of the page you linked:

    The method removes any elements and attributes that are considered XSS-unsafe, even if allowed by a passed sanitizer. Notably, the following elements are always removed: <script>, <frame>, <iframe>, <embed>, <object>, <use>, and event handler attributes.

    and

    The method will remove any XSS-unsafe elements and attributes, even if allowed by the sanitizer.

    Certified reddit moment, argumentative for the sake of being argumentative.

    Very quite literally at the VERY TOP of the page you linked

    Which is not at all what you complained about.

    Just admit that you dun goofd with this one mate.

    My big gripe is there's no way to exclude tags from set HTML.

    brother what. You are aware that exclude means to explicitly not include, right? You know, explicitly not include the tags that are ALWAYS blocked by setHTML, without using the unsafe method, like I said?