Webdevelopment en architectuur

Sanitizer API in Chrome 146: veilig HTML weergeven zonder XSS

Een ontwikkelaar werkt met code op drie beeldschermen aan een bureau.

Een CMS levert een alinea aan met een link en wat opmaak. De frontend haalt de inhoud op en toont die op de pagina. Dat lijkt routinewerk — totdat iemand via hetzelfde veld HTML meestuurt die de browser als actieve code interpreteert. Sinds Chrome 146 biedt de vernieuwde HTML Sanitizer API een veiligere route voor dit soort inhoud. Maar de belangrijkste vraag komt eerder: waarom behandelen we de gegevens eigenlijk als HTML?

Het risico begint bij de invoeging

Stel dat een applicatie een redactioneel tekstveld via een API ontvangt en het met innerHTML in een element plaatst:

container.innerHTML = cmsContent;

Als de bron onbetrouwbaar is, kan dat een XSS-risico opleveren. Het ophalen van gegevens via een API is op zichzelf niet het probleem; het risico ontstaat wanneer de browser onbetrouwbare inhoud als HTML interpreteert. Een kwaadwillend event-attribuut kan bijvoorbeeld code uitvoeren onder de rechten van de website.

Voor gewone labels, berichten of titels is HTML vaak niet nodig. container.textContent = userInput; behandelt de invoer als tekst in plaats van markup. Daarmee verdwijnt een hele categorie onnodige HTML-risico’s.

Wanneer opmaak wél nodig is

Een artikel uit een CMS bevat mogelijk koppen, links en lijsten die als HTML moeten worden getoond. De veilige methode Element.setHTML() kan een HTML-string parsen en verwijderen wat als XSS-onveilig wordt beschouwd. Chrome kondigde de vernieuwde Sanitizer API op 10 maart 2026 aan voor Chrome 146; volgens Chrome Developers was de nieuwe versie ook in Firefox beschikbaar.

const article = document.querySelector('#article');
const cmsContent = `
  <p>Welkom bij Dogteam</p>
  <img src="x" onerror="alert('XSS')">
`;

article.setHTML(cmsContent);

De methode verwijdert gevaarlijke attributen, waaronder eventhandlers zoals onerror. Dat geldt ook als een meegegeven sanitizerconfiguratie zo’n attribuut zou proberen toe te staan. Anders dan setHTMLUnsafe() is setHTML() ontworpen als XSS-veilige invoegmethode. Het voorbeeld illustreert het mechanisme op basis van de documentatie; ik heb dit niet zelf in een browser uitgevoerd.

Een nieuwe API vervangt geen contentbeleid

Niet iedere contentbron hoeft dezelfde opmaak te mogen gebruiken. Een productomschrijving vraagt misschien om paragrafen en lijsten, terwijl een redactioneel artikel ook tabellen nodig heeft. Leg daarom vast welke inhoud als platte tekst wordt verwerkt en welke via een gecontroleerd rich-text-component gaat.

Daarmee wordt ook duidelijk waar de vertrouwensgrenzen liggen. Een prop met de naam label zou niet stilzwijgend willekeurige HTML moeten accepteren; een veld als richContent kan wel een gedocumenteerd beleid hebben. Inspecteer niet alleen de publieke artikelpagina, maar ook previews, beheerinterfaces, reacties en externe plugins die HTML in de DOM plaatsen.

Wat doe je als setHTML ontbreekt?

MDN markeert setHTML() als beperkt beschikbaar: de methode werkt nog niet in alle veelgebruikte browsers. Dat is voor websites met uiteenlopende bezoekers en ingebouwde webviews een essentieel implementatiepunt. Controleer daarom de ondersteuning tijdens uitvoering, niet alleen op basis van een releasebericht:

if ('setHTML' in Element.prototype) {
  container.setHTML(cmsContent);
} else {
  // Gebruik een expliciet gecontroleerde,
  // veilig geconfigureerde sanitizerfallback.
}

De fallback is hier bewust geen volledige implementatie. Gebruik waar nodig een onderhouden sanitizingbibliotheek, controleer de configuratie en test deze in de doelbrowsers. Val nooit ongemerkt terug op ongefilterde innerHTML, want dan verdwijnt de bescherming precies bij de bezoekers zonder ondersteuning.

Test veiligheid én normale redactionele inhoud

Een sanitizer kan onveilige HTML verwijderen, maar daarmee is nog niet bewezen dat het eindresultaat voldoet aan alle functionele eisen. Controleer kwaadaardige invoer, onverwachte tags, event-attributen en onveilige links. Controleer óók of legitieme links, lijsten en tabellen blijven werken en of de inhoud toegankelijk is bij toetsenbordbediening en schermlezers.

Een goede Definition of Done maakt duidelijk welke HTML-bronnen zijn toegestaan, hoe de uitvoer wordt verwerkt, wat bij ontbrekende browserondersteuning gebeurt en welke regressietests beschikbaar zijn. Content Security Policy, output escaping in de juiste context en Trusted Types kunnen aanvullende beveiligingslagen zijn; ze vervangen elkaar niet automatisch.

De echte verbetering zit in minder onbetrouwbare HTML

De Sanitizer API maakt het eenvoudiger om noodzakelijke rich text veiliger weer te geven. Maar niet iedere string hoeft ooit door een HTML-parser. De duurzaamste architectuur beperkt daarom het aantal plaatsen waar onbetrouwbare HTML wordt ingevoegd en behandelt die resterende plekken consequent en controleerbaar.

Welke content gestructureerd wordt opgeslagen en hoe deze wordt gepresenteerd, hangt ook samen met de keuze voor een traditioneel, headless of hybride CMS.

Bronnen

Neem contact met ons op

Vertel ons waarmee we kunnen helpen; we reageren binnen twee werkdagen.

Alleen nodig als we je moeten terugbellen.
Vermeld bij sponsoring je bedrijfsnaam en voorstel. Voeg bij een correctie de pagina-URL toe.

We gebruiken je gegevens alleen om deze aanvraag af te handelen. Privacybeleid

Deel dit artikel

Deel dit artikel