371 points by todsacerdoti 5 days ago | 158 comments on HN
| Moderate positive
Contested
Editorial · v3.7· 2026-02-26 04:27:31 0
Summary Digital Security & Knowledge Advocates
This technical blog post advocates for web security standards through education and knowledge-sharing. The content champions the Sanitizer API as a developer tool to prevent cross-site scripting attacks, framing security as a collective good. Mozilla's non-profit role and open-access publishing support education and freedom of expression, though the site's use of Google Analytics tracking creates tension with the privacy protection advocacy.
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".
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
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.
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.
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.
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.
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.
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.
The idea is you wouldn't mix innerHTML and setHTML, you would eliminate all usage of innerHTML and use the new setHTMLUnsafe if you needed the old functionality.
You are right that the concept of "safe" is nebulous, but the goal here is specifically to be XSS-safe [1]. Elements or properties that could allow scripts to execute are removed. This functionality lives in the user agent and prevents adding unsafe elements to the DOM itself, so it should be easier to get correct than a string-to-string sanitizer. The logic of "is the element currently being added to the DOM a <script>" is fundamentally easier to get right than "does this HTML string include a script tag".
The main case I can think of is wanting some forum functionality. Perhaps you want to allow your users to be able to write in markdown. This would provide an extra layer of protection as you could take the HTML generated from the markdown and further lock it down to only an allowed set of elements like `h1`. Just in case someone tried some of the markdown escape hatches that you didn't expect.
Using an allowlist based Sanitizer you are definitely less likely to shoot yourself in the foot, but as long as you use setHTML you can't introduce XSS at least.
When browsers implement a variant that lets you separate data and code perhaps. That's what I expected when reading the headline: setHtml(code, data, data, ...), just like parameterised SQL works: prepare("select rowid from %s where time < %n", tablename, mynumber)
This new method they've cooked up would be called eval(code,options) if html was anything other than a markup language
> If the default configuration of setHTML( ) is too strict (or not strict enough) for a given use case, developers can provide a custom configuration that defines which HTML elements and attributes should be kept or removed.
will strip all elements out. That's not too difficult.
Plus this is defense-in-depth. Backends will still need to sanitize usernames on some standard anyhow (there's not a lot of systems out there that should take arbitrary Unicode input as usernames), and backends SHOULD (in the RFC sense [1]) still HTML-escape anything they output that they don't want to be raw HTML.
`setHTML` is meant as a replacement for `innerHTML`. In the use case you describe, you would have never wanted `innerHTML` anyway. You'd want `innerText` or `textContent`.
Ideally you should be able to set a global property somewhere (as a web developer) that disallows outdated APIs like `innerHTML`, but with the Big Caveat that your website will not work on browsers older than X. But maybe there's web standards for that already, backup content if a browser is considered outdated.
> 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.
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.
Content explicitly educates developers about security best practices. Knowledge sharing supports right to education and technical literacy. Explains CSP history and Sanitizer API design, building developer competency.
FW Ratio: 71%
Observable Facts
Article provides technical education on XSS prevention and Sanitizer API.
Historical context given: 'Firefox...spearheading the Content-Security-Policy (CSP) standard in 2009.'
Code examples provided: 'document.body.setHTML(`<h1>Hello my nam' (truncated but present).
Content explains why CSP adoption failed: 'requires significant architectural changes for existing web sites.'
No registration or payment required to access educational content.
Inferences
Technical documentation with code examples empowers developers to implement security protections, supporting education right.
Article directly addresses freedom of expression through technical education. Content advocates for developers' capacity to protect user data and security. Transparent attribution supports freedom of expression infrastructure.
FW Ratio: 63%
Observable Facts
Article published without paywall or registration barrier.
Three authors identified by name with gravatar links for attribution.
Publication date and category tags (Featured Article, Firefox, Web Developers) provide transparent metadata.
Content sourced from Mozilla Foundation, a non-profit organization.
Technical knowledge shared to empower developers with security literacy.
Inferences
Open access + attribution + non-profit ownership directly support Article 19 infrastructure for free expression.
Educating developers about security standards expands their capacity to speak and act freely by reducing exploitation risk.
Standardized solutions (setHTML) democratize security knowledge rather than gatekeeping behind proprietary tools.
Content participates in scientific and technical progress through standardization work. Sanitizer API represents collective advancement in web security knowledge.
FW Ratio: 60%
Observable Facts
Article discusses standardized Sanitizer API: 'new standardized Sanitizer API provides a straightforward way.'
Mozilla's historical role in standards: 'Firefox has been deeply involved in solutions for XSS from the beginning.'
Article anticipates adoption: 'We expect other browsers to follow soon.'
Inferences
Participation in web standards development advances collective technical progress available to all.
Non-profit sponsorship ensures scientific progress serves public interest rather than proprietary interests.
Content explicitly advocates for safer web through technical security standards. Language emphasizes collective benefit ('advancing a safer web for everyone') aligned with UDHR's universal dignity framing.
FW Ratio: 67%
Observable Facts
Article title frames setHTML as 'Stronger XSS Protection' in Firefox 148.
Opening statement: 'advancing a safer web for everyone.'
Three authors clearly identified by name: Tom Schuster, Frederik Braun, Christoph Kerschbaumer.
Publication date explicitly stated: February 24, 2026.
Inferences
The framing positions web security as a collective good rather than individual concern, aligning with UDHR's universal principles.
Transparent authorship and dating supports accountability, consistent with Article 19 on freedom of expression.
Content addresses adequate standard of living through security protection. XSS attacks can compromise financial data and personal security; preventing XSS indirectly protects users' economic welfare.
FW Ratio: 50%
Observable Facts
Article notes XSS attackers 'could monitor and manipulate user interactions and continually steal user data.'
Inferences
Protection against data theft supports users' ability to maintain financial security and adequate living standards.
Content indirectly supports social and international order for human rights by advocating for security standards that protect all users globally from exploitation.
FW Ratio: 50%
Observable Facts
Article frames XSS protection as universal goal: 'advancing a safer web for everyone.'
Inferences
Global security standards contribute to international order protective of digital rights.
Site implements Google Analytics and GTM tracking with UTM parameter removal utility, indicating awareness of privacy concerns but continued analytics deployment.
Terms of Service
—
Terms of service not observable in provided content.
Identity & Mission
Mission
+0.20
Article 19 Article 27
Mozilla's stated mission around open web and developer empowerment aligns with knowledge-sharing and technical security education.
Editorial Code
+0.05
Article 19
Technical blog format with clear author attribution and date stamps supports editorial transparency.
Ownership
+0.10
Article 19
Mozilla Foundation ownership as non-profit organization supports commitment to public interest over profit-driven content.
Access & Distribution
Access Model
+0.15
Article 26
Open access technical content published without paywall or registration barrier.
Ad/Tracking
-0.10
Article 12
Google Analytics and GTM tracking present on page reduces privacy score despite Mozilla's privacy advocacy.
Open access model (no paywall) makes technical education freely available to all developers globally. WordPress accessibility standards support universal usability. Clear explanations reduce barriers to learning.
Open access publication (no paywall or registration). Clear authorship attribution (Tom Schuster, Frederik Braun, Christoph Kerschbaumer). Mozilla Foundation ownership (non-profit) supports public interest over profit-driven information gatekeeping. Content freely redistributable.
Google Analytics (UA-35433268-8) and Google Tag Manager (G-5WVW12ST9K) tracking scripts present. Analytics fingerprinting contradicts privacy advocacy.
build 1ad9551+j7zs · deployed 2026-03-02 09:09 UTC · evaluated 2026-03-02 11:31:12 UTC
Support HN HRCB
Each evaluation uses real API credits. HN HRCB runs on donations — no ads, no paywalls.
If you find it useful, please consider helping keep it running.