8 ms·
Element: setHTML() method
- michalpleban 1y agoSo is this basically a safe version of innerHTML?
- Octoth0rpe 1y agoYes, although a slightly more relevant way of putting it would be that it's an inbuilt DOMPurify (dompurify being an npm package commonly used to sanitize html before injecting it).
- ngold 1y agoIs this basically doing the same thing as https now? But for http, and firefox just never implemented a simple fix for it's entire existence until now? I obviously know nothing about this, but I still find it fascinating. Or am I off my block.
- masklinn 1y agoThis has nothing whatsoever to do with http.
- bilekas 1y agoXSS isn't related to https/ssl, ssl is the secure conncetion between you and the server, but xss is the injection of data into the site which will be executed in your browser in this case. The connection isnt relevant. https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/XSS#overview https://developer.mozilla.org/en-US/docs/Web/Security/Attack...
- intrasight 1y agoI'm confused as to why you need a "safe" version if you're the one generating and injecting the HTML.
- evbogue 1y agoWhy should a web page only have a single person generating and injecting HTML into it?
- intrasight 1y agoA single company. Why would I let another company inject HTML into my page?
- afavour 1y agoThere's this newfangled concept called social media where you let other people post content that exists on your web site. You're rarely allowed to post HTML because of the associated issues with sanitizing it. setHTML could help with that.
- president_zippy 1y agoI just had a flashback to the heyday of MySpace. Now that I think about it though, Neocities has the "social networking" of being able to discover other people's pages and give each other likes and comments. Hmmm...
- mpeg 1y agoOr CMS content, or even anything that comes from the user outside of social media content and could cause a reflected XSS for example, a search query, or a redirect url, or a million other things
- intrasight 1y agoThe analogy doesn't hold markup ;) Whether I generate a whole page or generate a partial page and then add HTML to it is equivalent from a safety perspective.
- matmo 1y agoIsn't this kinda like asking "why does my gun need a safety if I'm the only one consciously pulling the trigger"?
- evilpie 1y agoWe enabled this by default in Firefox Nightly (only) this week.
- spankalee 1y agoI'll be very excited to use this in Lit when it hits baseline. While lit-html templates are already XSS-hardened because template strings aren't forgeable, we do have utilities like `unsafeHTML()` that let you treat untrusted strings as HTML, which are currently... unsafe. With `Element.setHTML()` we can make a `safeHTML()` directive and let the developer specify sanitizer options too.
- StrauXX 1y agoWhy don't you use DOMPurify right now? It's battle tested and supports configs just like this proposal.
- ffsm8 1y agoWhy would the framework do that? The app developers can still use that right now, but if the framework forces it's usage it'd unnecessarily increase package size for people that didn't need it.
- spankalee 1y agoOne, lit-html doesn't have any dependencies. Two, even if we did, DOMPurify is ~2.7x bigger than lit-html core (3.1Kb minzipped), and the unsafeHTML() directive is less than 400 bytes minzipped. It's just really big to take on a sanitizer, and which one to use is an opinion we'd have to have. And lit-html is extensible and people can already write their own safeHTML() directive that uses DOMPurify. For us it's a lot simpler to have safe templates, an unsafe directive, and not parse things to finely in between. A built-in API is different for us though. It's standard, stable, and should eventually be well known by all web developers. We can't integrate it with no extra dependencies or code, and just adopt the standard platform options.
- 1y ago
- redbell 1y ago> This feature is not Baseline because it does not work in some of the most widely-used browsers. This is interesting, but it appears to be in its early days as none of the major browsers seem to support it.. yet.
- draw_down 1y ago[dead]
- JadeNB 1y agoA sibling comment by evilpie says that it is enabled in Firefox Nightly: https://news.ycombinator.com/item?id=45674985 https://news.ycombinator.com/item?id=45674985
- MarsIronPI 1y agoActually, it exists behind an about:config as far back as 138. So if you enable it, it even works in the current ESR.
- CaptainOfCoit 1y agoReally happy to see it, after 25 years (https://www.bugcrowd.com/glossary/cross-site-scripting-xss/ https://www.bugcrowd.com/glossary/cross-site-scripting-xss/) of surviving without it. It always struck me as an obvious missing part of the DOM API, and I still don't know why it took this long time. But mostly I'm just happy that it's finally here, I do appreciate all the hard work people been doing to get this live.
- theendisney 1y agoYes <sc<script>ript>
- bawolff 1y agoI think DOM api people just really wanted everyone to use .appendChild() methods. I think there is an interesting lesson here about how security is partially an ergonomic problem.
- AlienRobot 1y agoGreat functionality, terrible name.
- varun_ch 1y agoI sometimes wonder whether what the DOM APIs could look like in a hypothetical world where we could start over with everything.
- hexasquid 1y agoIt looks like this isn't a standard yet.
- jonathrg 1y agoWhy? Does it not set the HTML?
- netsharc 1y agoIt doesn't say "There's a lot of hidden sanitizing stuff inside this method" from the name... Something like "setSafeHTML()" would be preferable. (Since it's Mozilla, there should be a few committee meetings to come up with the appropriate name)...
- hoppp 1y agoWell ,could it be safelySetHTML instead of setSafeHTML ? The second one could imply the HTML is already safe while the first one is safe way to set html. If it's just setHTML then it could imply that don't care if its safe or not.
- AlienRobot 1y agoThere is already an innerHTML property for elements. This doesn't set the outer HTML, so it's literally setInnerHTML2.
- hexasquid 1y agoAfter a minute of digging, found discussion here: https://github.com/WICG/sanitizer-api/issues/100 https://github.com/WICG/sanitizer-api/issues/100 Perhaps it can be reopened (or a new issue can be opened) regarding naming.
- dzogchen 1y agoNeat. I think once this is adopted by HTMX (or similar libraries) you don't need to sanitize on the server side anymore?
- dylan604 1y agoDo you honestly feel that we will ever be in a place for the server to not need to sanitize data from the client? Really? I don't. Any suggestion to me of "not needing to sanitize data from client" will immediately have me thinking the person doing the suggesting is not very good at their job, really new, or trying to scam me. There's no reason to not sanitize data from the client, yet every reason to sanitize it.
- jsmith99 1y agoIt's arguably easier just to sanitise at display time otherwise you have problems like double escaping.
- bpt3 1y agoEasier does not mean better, which seems to be true in this case given the many, many vulnerabilities that have been exploited over the years due to a lack of input sanitization.
- padjo 1y agoIn this case easier is actually better. Sanitize a string at the point where you are going to use it. The locality makes it easy to verify that sanitation has been done correctly for the context. The alternative means you have to maintain a chain of custody for the string and ensure it is safe.
- dylan604 1y agoif you are using it at the client, sure, but then why is the server involved? if you are sending it to the server, you need to treat it like it is always coming from a hacker with very bad intentions. i don't care where the data comes from, my server will sanitize it for its own protection. after all, just because it left "clean" from your browser does not mean it was not interfered with elsewhere upstream TLS be damned. if we've double encoded something, that's fine, it won't blow up the server. at the end of that day, that's what is most important. if some double decoding doesn't happen correctly on the client, then <shrugEmoji>
- ishouldbework 1y ago> It then removes any HTML entities that aren't allowed by the sanitizer configuration, and further removes any XSS-unsafe elements or attributes — whether or not they are allowed by the sanitizer configuration. Emphasis mine. I do not understand this design choice. If I explicitly allow `script` tag, why should it be stripped? If the method was called setXSSSafeSubsetOfHTML sure I guess, but feels weird for setHTML to have impossible-to-override filter.
- evilpie 1y agoIf you want to use an XSS-unsafe Sanitizer you have to use setHTMLUnsafe.
- jmull 1y agoI guess they are going for a safe default... the idea is people who don't carefully read the docs or carefully monitor the provenance of their dynamically generated HTML will probably reach for "setHTML()". Meanwhile, there's "setHTMLUnsafe()" and, of course, good old .innerHTML.
- strbean 1y agoThis is primarily an ergonomic addition, so it kinda makes sense to me to not make the dangerous footguns more ergonomic in the process. You can still assign `innerHTML` etc. to do the dangerous thing.
- hsbauauvhabzb 1y agoIdeally this should be called dangerouslySetInnerHTML but hindsight blah blah
- meowface 1y agoI agree, though I also agree with the parent that the method name is a little bit confusing. "safeSetHTML" or "setUntrustedHTML" or something would be clearer.
- strbean 1y ago
- ibowankenobi 1y agoThe API design could be better. Document fragments are designed to be reused. It should accept an optional fragment key which accepts a document fragment.If not a fragment, throw, if has children, empty contents first.
- spankalee 1y agoIn what way are document fragments meant to be reused? They empty their contents into the new parent when they're appended, so they can't be meaningfully appended a second time without rebuilding them. `<template>` is mean to be reused, since you're meant to clone it in order to use it, and then you can clone it again.
- ibowankenobi 1y agoYou can absolutely reuse a document fragment https://ibrahimtanyalcin.github.io/Cahir/ https://ibrahimtanyalcin.github.io/Cahir/ the whole rendering uses a single fragment.
- halapro 1y agoYou can absolutely not reuse a DocumentFragment. The moment you append it to a node, the fragment is emptied. https://dom.spec.whatwg.org/#mutation-algorithms https://dom.spec.whatwg.org/#mutation-algorithms > To insert a node into a parent before a child [...]: > If node is a DocumentFragment node: > Remove its children
- ibowankenobi 1y agoPeople have trransformed their brain because of using frameworks and do not understand how DOM works. I pasted A LIVE example to prove you wrong and you will still attach me whatwg link. YES , when you append it is emptied! Keep a reference to the same fragment and REAPPEND to it! REUSE it. If you want to empty without appending, call replaceChildren() since it inherits from Node. Why are people stubborn on things they dont know????
- padjo 1y agoAs someone who has dealt with more than my fair share of content injection vulnerabilities over the years this is great to see at last. It’s kinda crazy that this only coming now while other, more cumbersome solutions like CSP have been around for years.
- modinfo 1y agoCursor build a pseudo-sethtml: https://github.com/skorotkiewicz/pseudo-sethtml https://github.com/skorotkiewicz/pseudo-sethtml
- exdeejay_ 1y agoThis code only does the most basic and naive regex filtering that even a beginner XSS course's inputs would work against. With the Node example code and input string: <p>Hello <scr<script>ipt>alert(1)</scr<script>ipt> World</p> The program outputs: $ node . <p>Hello <script>alert(1)</script> World</p> { sanitizedHTML: '<p>Hello <script>alert(1)</script> World</p>', wasModified: true, removedElements: [], removedAttributes: [] } Asking a chatbot to make a security function and then posting it for others to use without even reviewing it is not only disrespectful, but dangerous and grossly negligent. Please take this down.
- codedokode 1y agoI wonder why Cursor chose regex approach when it is widely known that it is a wrong method. Is it a result of training on low-quality forums for beginners?
- deleted 1y ago[deleted]
- foldr 1y agoIt does seem like a weirdly bad result. I got something more sensible that used DOMParser when I gave GPT-5 the following prompt: > Write a JavaScript function for sanitizing arbitrary untrusted HTML input before setting a DOM element’s innerHTML attribute. I won’t post it here in case someone tries to use it, but it wasn’t just doing regex munging.
- bilekas 1y agoIt doesn't really matter, but if you ask it the exact same prompt it will give different results everytime. And if you don't know how to write one properly yourself, you really shouldn't be blindly trusting Ai to produce something correctly. But these are the source of all future employment of developers and engineers who actually know things.
- _the_inflator 1y agoMaybe it is then time for having something that is beyond "use strict" at the beginning auf a JavaScript document as one option to use the statement. I think a config object in which you define for script options like sanitization and other script configuration might be helpful. After all, there almost always need to be backward compatibility be ensured, and this might work. I am no spec guy, it is just an idea. React makes use of "use client/server", so this would be more central and explicit.
- ricardobeat 1y agoESM modules are already in strict mode by default.
- rictic 1y agoA somewhat related spec, at the page level rather than the module level, are Content Security Policies, which let a page disable various unsafe browser features for a page: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP One of my favorite features in there is trusted types enforcement: https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Typ... Lets you create your own API for what code is allowed to create arbitrary, potentially unsafe HTML at runtime, so you can allow secure templating systems but disallow code that just concats strings together naively.
- cheeaun 1y agoFound a polyfill here https://github.com/mozilla/sanitizer-polyfill https://github.com/mozilla/sanitizer-polyfill
- dkyc 1y agoThis just uses DOMPurify under the hood
- Izkata 1y ago...yes, that's what a polyfill is: a javascript implementation of a new spec that's only applied when the current browser doesn't yet support the new spec. This lets devs start using it right away, then when it has enough support across browsers the polyfill can be removed without changing their code.
- sergeykish 1y agoSo `.setHTML("<script>...</script>")` does not set HTML?
- xp84 1y agoSounds reasonable enough to me. 99.99% of the times you’re in an actual script, if you mean to execute code, you’d just execute it yourself, rather than making a script tag full of code and sticking that tag into a random DOM element. That’s why the default wouldn’t honor the script tag and there’d be an “unsafe” method explicitly named as such to hint you that you’re doing something weird.
- amelius 1y agoBut it breaks an abstraction. Sometimes you just want to take working HTML and insert it into a document. It will be painful if suddenly this does not work, and you have to dig into the documentation to see why.
- rictic 1y agoIt is also painful when your app gets hacked, accounts get taken over and abused, user data is compromised, and so on. For serious sites it's worth the pain to turn on security enforcement features.
- amelius 1y agoOk, but be sure to make it optional. Putting 10 locks on your door is great for security, but it's not for everyone. And instead of this security feature some might want to take a more fundamental look at security which might lead them to a completely different design. Again, make it optional.
- kibwen 1y agoIt is optional. Use setHTMLUnsafe.
- codedokode 1y agoI don't like this. This could be implemented as a JS library. I believe browsers should provide the minimal API so that they are smaller and easier to create. As for safe alternative to innerHTML, it is called innerText.
- csmantle 1y agoI think innerText and setHTML() have different purposes. The former inserts the whole string as a text leaf, while the latter tries to preserve structures that are meaningful in context. --- Libraries can surely do the same job, but then the exact behavior would vary among a sea of those libs. Having specs defined [0] for such an interface would hopefully iron out much of these variations, as well as enabling some performance gains. [0]: https://wicg.github.io/sanitizer-api/#dom-element-sethtml https://wicg.github.io/sanitizer-api/#dom-element-sethtml
- codedokode 1y agoAnd if you need something that is not in a spec, you have to use a library anyway. Also the point was that browser should be as simple as possible and not like a whole new OS.
- codezero 1y agoinnerText has wildly inconsistent implementations across browsers.
- petralithic 1y ago> I believe browsers should provide the minimal API so that they are smaller and easier to create. That ship has long since sailed. Browsers are so complex that it takes quite some effort to support the various levels of 9s of the percentage of compatibility with standards, not to mention the browser makers themselves define many of the standards.
- deleted 1y ago[deleted]
- CGamesPlay 1y agoIs “XSS-unsafe” precisely defined anywhere? I assume it means “any access to the JS interpreter”, but assuming in this context seems decidedly unsafe.
- pyth0 1y agoIt appears you can tune what is sanitized from the input via the "sanitizer" optional parameter. The default sanitizer is however defined in a spec linked on the docs page [1] with the actual sanitize operation specified as well [2]. [1] https://wicg.github.io/sanitizer-api/#dom-element-sethtml https://wicg.github.io/sanitizer-api/#dom-element-sethtml [2] https://wicg.github.io/sanitizer-api/#sanitize https://wicg.github.io/sanitizer-api/#sanitize
- CGamesPlay 1y agoAh, perfect, the "remove unsafe" operation is what I was looking for. It includes a list of elements and a list of attributes. These appear to apply regardless of the sanitizer configuration you use, the original MDN link demonstrates allowlisting "script" but seeing that it is removed anyways. https://wicg.github.io/sanitizer-api/#sanitizerconfig-remove-unsafe https://wicg.github.io/sanitizer-api/#sanitizerconfig-remove...
- Traubenfuchs 1y agoSo this is the easier, built in successor to innerHTML = trustedTypes.createPolicy('myPolicy', { createHTML: (input) => DOMPurify.sanitize(input, {RETURN_TRUSTED_TYPE: true}) }).createHTML() ?
- textlanes33 1y agoThis is goood news for me. Finally! A safer and more predictable alternative to innerHTML.
- ulrischa 1y agoSince 5 years everybody says Jquery us no longer necessary. But really baisc function like this take a long time for replacing Jquery
- halapro 1y agojQuery does not sanitize HTML. This is why jQuery is no longer necessary, even if people think it is.
- ulrischa 1y agoThere is the jquery bashing again. let sanitizedHTML = $('<div>').text(unsanitizedHTML).html();
- wccrawford 1y agoYou can 100% do that same thing without jQuery. It's not even complicated. And that is not what the new .setHTML() does.
- awayredbarron 1y ago>Verbose I/O element Parsing > "DocumentFragment" Returns proc. exit status [0]/[1] for browser HTML incompatability.
- xnorswap 1y agoThat's really good to hear. I've found LLMs will happily generate XSS vulnerable code, which will make things worse for a while until they can be trained better. In fact, I found it really difficult to get claude-code to use templating libraries and not want to default to hand-written templating with XSS vulnerabilties and injecting content directly, even after going through options with it. There's also a difference between escaping and sanitisation which can be tricky to handle and track, and it can even be dangerous to try to mix different approaches or sanitizers. Having a safe backstop in the form of setHTML() to use will be a fantastic addition to narrow the scope of ways to get it wrong.
- tartoran 1y agoThis whole page renders extremely poorly on mobile, beyond usable I'd say.
- waldothedog 1y agoWorking well for me on mobile!
- erickotato 1y agoI don't really get it. Why this is needed on client? If all we want is to prevent XSS attacks, wouldn't it be more effective to sanitize on server? Am I missing something?