28 comments

[ 2.8 ms ] story [ 54.2 ms ] thread
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".

> 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".

What is safe depends on where the sanitized HTML is going, on what you're doing with it.

It isn't possible to "sanitize HTML" after collecting it so that, when you use it in the future, it will be safe. "Safe" is defined by the use.

But it is possible to sanitize it before using it, when you know what the use will be.

> it's not at all clear which is which from the names. Ideally you design that in from the [start]

It was, and there is: setting elementNode.textContent is safe for untrusted inputs, and setting elementNode.innerHTML is unsafe for untrusted inputs. The former will escape everything, and the latter won't escape anything.

You are right that these "sanitizers" are fundamentally confused:

> "HTML sanitization" is never going to be solved because it's not solvable.¶ There's no getting around knowing whether or any arbitrary string is legitimate markup from a trusted source or some untrusted input that needs to be treated like text. This is a hard requirement.

<https://news.ycombinator.com/item?id=46222923>

The Web platform folks who are responsible for getting fundamental APIs standardized and implemented natively are in a position to know better, and they should know better. This API should not have made it past proposal stage and should not have been added to browsers.

Yeah someone tells me something has been made “safe” is nice but unless I know exactly what that means … it’s easy to say safe by someone who doesn’t have to deal with it when the bad corner case happens.

Oh and it’s safe… in this browser… not that one, so this idea of safety is kinda dead to me for now.

A rather deceptive title, given that 'innerHTML' isn't going away.
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.
Nice one. Will there be any impact on __dangerouslySetInnerHTML (React)?
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?

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.

> never allow the user to add any sort of HTML too the document.

What about when the author of the page wants to add large html fragments to the page?

Are you saying that you cannot think of a single use for this, considering how often innerHTML is being used?

at what point can we consider the development of "set this element's text/html" to be done?
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.

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)
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.
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.

My corporate firewall blocks it due to the "hacks" in the subdomain / url. This is silly.
That's why the DNS for hackernews is news.ycombinator.com and not hackernews.org
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.

Kids in the '90s:

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

  div.innerHTML = "Hello " + user.name;
Kids in the '30s:

  "Summarize this email:  " + email.contents
Prompt injection is just the same problem on a new technology. We didn't learn anything from the 90s.
Tangential but it's amazing in 2026 browsers still don't ship a native DOM morph/merge API like morphdom or idiomorph.
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.
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.

What's the benefit over Trusted Types?