logoalt Hacker News

Goodbye InnerHTML, Hello SetHTML: Stronger XSS Protection in Firefox 148

310 pointsby todsacerdotitoday at 1:04 PM143 commentsview on HN

Comments

entunotoday at 1:29 PM

This kind of thing always makes me nervous, because you end with a mix of methods where you can (supposedly) pass arbitrary user input to them and they'll safely handle it, and methods where you can't do that without introducing vulnerabilities - but it's not at all clear which is which from the names. Ideally you design that in from the state, so any dangerous functions are very clearly dangerous from the name. But you can't easily do that down the line.

I'm also rather sceptical of things that "sanitise" HTML, both because there's a long history of them having holes, and because it's not immediately clear what that means, and what exactly is considered "safe".

show 13 replies
simonwtoday at 1:30 PM

Great to see this start to show up, but it looks like it will be a while before browser support is widely distributed enough to rely on it being present: https://caniuse.com/mdn-api_element_sethtml

show 1 reply
Aachentoday at 2:22 PM

So you can still inject <h1> or <br><br><br>... etc into your username, in the given example

Preventing one bug class (script execution) is good, but this still allows arbitrary markup to the page (even <style> CSS rules) if I'm reading the docs correctly. You could give Paypal a fresh look for anyone who opens your profile page, if they use this. Who would ever want this?

show 10 replies
jjcmtoday at 9:12 PM

What I really want is a <sandbox> element that can safely run dangerous code, not something that modifies dangerous code.

Iframes have significant restrictions as they can’t flow with the DOM. With AI and the increase in dynamic content, there’s going to be even more situations where you run untrusted code. I want configurable encapsulation.

dogtimeimmortaltoday at 5:42 PM

Title was a bit rage-baity. And I think you can already do sanitation by writing a function to check input before passing it to innerHTML?

This really just seems like another attempt at reinventing the wheel. Somewhat related, I find it ironic how i cannot browse hacks.mozilla.org in my old version of firefox("Browser not supported"). Also, developer.mozilla.org loads mangled to various degrees in current versions of palemoon, basilisk, and seamonkey

It's like there is some sort of "browser cartel" trying to screw up The Web.

show 1 reply
cogman10today at 2:26 PM

Seems like this has a bunch of footguns. Particularly if you interact with the Sanitizer api, and particularly if you use the "remove" sanitizer api.

Don't get me wrong, better than nothing, but also really really consider just using "setText" instead and never allow the user to add any sort of HTML too the document.

show 3 replies
pyrolisticaltoday at 7:50 PM

And for those who want a better innerHTML, use insertAdjacentHTML https://developer.mozilla.org/en-US/docs/Web/API/Element/ins...

I don’t ever use it with user input, but use it often when building SPA without frameworks

tuyiowntoday at 1:50 PM

This is nice. The best part is that all aspects of network access are now properly controlled so that security transitioned from a chain of trusted code to a chain of trusted security setup on hosts, with existing workable safe defaults.

kevincloudsectoday at 4:23 PM

naming the old behavior setHTMLUnsafe is what did it for me. security features that require developers to opt in don't work. making the unsafe path feel unsafe does.

shevy-javatoday at 4:59 PM

Well, the name SetHTML, or let's say:

    .set_html()
Makes objectively more sense than:

    .inner_html()
    .inner_html =
    .set_inner_html()
It is a fairly small thing, but ... really. One day someone should clean up the mess that is JavaScript. Guess it will never happen, but JavaScript has so many strange things ...

I understand that this here is about protection against attacks rather than a better API design, but really - APIs should ideally be as great as possible the moment they are introduced and shown to the public.

show 1 reply
pier25today at 6:56 PM

Tangential but it's amazing in 2026 browsers still don't ship a native DOM morph/merge API like morphdom or idiomorph.

dvhtoday at 6:01 PM

Kids in the '90s:

  SQL("select * from user where name = " + name);
Kids in the '20s:

  div.innerHTML = "Hello " + user.name;
show 1 reply
austin-cheneytoday at 8:02 PM

Another solution is just use this at the start of your code:

    delete Element.prototype.innerHTML;
Then assignments to innerHTML do not modify the element's textContent or child node list and assignments to it will not throw an error.
bryanrasmussentoday at 4:14 PM

is there any situation where innerHTML would be preferable? I could suppose it might be more performant and so if you were constructing something that was not open to XSS it might theoretically be better (with the usual caveat that people always make mistakes about this kind of thing)

dbvntoday at 2:44 PM

at what point can we consider the development of "set this element's text/html" to be done?

show 1 reply
antonyhtoday at 1:48 PM

A rather deceptive title, given that 'innerHTML' isn't going away.

show 1 reply
bingemakertoday at 1:59 PM

Nice one. Will there be any impact on __dangerouslySetInnerHTML (React)?

shadowgovttoday at 3:31 PM

Oh, that's nice-to-have. Good work, Mozilla.

It would close the loop better if you could also use policy to switch off innerHTML in a given page, but definitely a step in the right direction for plain-JavaScript applications.

giancarlostorotoday at 5:05 PM

My corporate firewall blocks it due to the "hacks" in the subdomain / url. This is silly.

show 1 reply
umairnadeem123today at 8:38 PM

[dead]

octoclawtoday at 2:07 PM

[dead]