5 puntos por GN⁺ 2026-02-26 | 2 comentarios | Compartir por WhatsApp
  • Para prevenir los ataques XSS, una de las principales vulnerabilidades de la web, Firefox se convierte en el primero en dar soporte a la Sanitizer API estandarizada
  • Al usar el método setHTML() en lugar de innerHTML, el HTML no confiable se sanitiza automáticamente antes de insertarse en el DOM, eliminando scripts maliciosos
  • Si la configuración predeterminada resulta demasiado estricta o insuficiente, los desarrolladores pueden controlar qué elementos y atributos se permiten mediante una configuración personalizada
  • Esta función de Firefox, combinada con Trusted Types, eleva el nivel de seguridad de la web en general y permite prevenir XSS incluso sin contar con un equipo de seguridad dedicado

La vulnerabilidad XSS y la respuesta de Firefox

  • El cross-site scripting (XSS) ocurre cuando un atacante inserta HTML o JavaScript arbitrario a través de contenido introducido por el usuario
    • Con ello, el atacante puede vigilar la interacción del usuario o robar datos
    • XSS ha sido clasificado durante casi 10 años como una de las 3 principales vulnerabilidades web (CWE-79)
  • Firefox ha reforzado la defensa contra XSS desde 2009 liderando el estándar Content-Security-Policy (CSP)
    • CSP limita los recursos que un sitio web puede cargar y ejecutar
    • Sin embargo, requería cambios en la estructura de los sitios existentes y revisiones de seguridad continuas, por lo que su adopción masiva tenía limitaciones

El papel de Sanitizer API y setHTML()

  • La Sanitizer API ofrece un método estandarizado para transformar HTML malicioso en una forma inocua
    • En el código de ejemplo, el elemento <img src="x" onclick="alert('XSS')"> se elimina y solo queda <h1>Hello my name is</h1>
  • El método setHTML() ejecuta automáticamente el proceso de sanitización al insertar HTML, garantizando un comportamiento seguro por defecto
    • Reemplazar la asignación con innerHTML por setHTML() permite una fuerte defensa contra XSS
  • Si la configuración predeterminada resulta demasiado estricta o flexible, los desarrolladores pueden definir los elementos y atributos HTML permitidos mediante una configuración personalizada
    • Para experimentar, se puede utilizar la herramienta Sanitizer API playground

Combinación con Trusted Types

  • La Trusted Types API proporciona una capa adicional de seguridad al controlar de forma centralizada el parseo y la inserción de HTML
    • Al usar setHTML(), se puede aplicar fácilmente una política de Trusted Types
    • Una política estricta puede permitir solo setHTML() y bloquear otros métodos de inserción riesgosos, ayudando a prevenir futuras regresiones de XSS

Mejora de seguridad en Firefox 148

  • Firefox 148 admite tanto Sanitizer API como Trusted Types, lo que mejora considerablemente el nivel de seguridad por defecto
  • Los desarrolladores pueden prevenir XSS con simples cambios de código sin necesidad de políticas de seguridad complejas ni de un equipo de seguridad aparte
  • Se espera que la adopción de este estándar contribuya a extender un entorno web más seguro en todos los navegadores

Resumen

  • Firefox 148 permite a los desarrolladores web bloquear fácilmente ataques XSS mediante el método setHTML() y la Sanitizer API
  • Esta función complementa las limitaciones de CSP y marca un paso importante para establecer un método de inserción de HTML seguro por defecto como estándar web
  • Su combinación con Trusted Types permite mantener la seguridad a largo plazo y evitar regresiones de XSS
  • En consecuencia, Firefox está liderando la transición hacia un entorno web donde la seguridad es el valor predeterminado

2 comentarios

 
huiya 2026-02-26

Oh, sí, definitivamente se necesitaba algo así. Estaría genial que todos los navegadores lo soportaran.

 
GN⁺ 2026-02-26
Opiniones de Hacker News
  • Este tipo de función siempre me da un poco de desconfianza
    porque se mezclan métodos que manejan de forma segura entradas arbitrarias del usuario con otros que no, y solo por el nombre es difícil distinguirlos
    Idealmente, desde el principio las funciones peligrosas deberían dejarlo claro en el nombre
    Además, la idea misma de “sanitizar” HTML es ambigua, y es difícil saber si realmente es seguro

    • Es cierto que la definición de “seguro” es ambigua, pero aquí el objetivo es que sea seguro contra XSS
      elimina elementos o atributos que puedan ejecutar scripts, y esta lógica corre dentro del motor del navegador, así que maneja esto con más precisión que un sanitizer basado en cadenas
      Para más detalles, consulta la documentación de MDN sobre setHTML
    • En realidad ya hay una distinción clara
      elementNode.textContent es seguro incluso con entradas no confiables, y elementNode.innerHTML no lo es
      el primero hace escape de todos los caracteres, y el segundo no hace escape de nada
      También hay quienes opinan que la “sanitización de HTML” es un problema imposible de resolver en el fondo
      véase este comentario para una discusión relacionada
      una API así nunca debió pasar la etapa de propuesta
    • En vez de mezclar innerHTML y setHTML, debería haberse diseñado eliminando por completo innerHTML y usando setHTMLUnsafe cuando se necesite el comportamiento anterior
    • Ojalá los desarrolladores web pudieran desactivar globalmente APIs antiguas como innerHTML
      aunque entonces el sitio podría no funcionar en navegadores viejos
    • Si sirves la página con el encabezado Content-Security-Policy: require-trusted-types-for 'script', puedes bloquear que se pasen cadenas normales a métodos sin sanitizer
  • Si, como en el ejemplo, se pueden insertar etiquetas como <h1> o <br> en el nombre de usuario, aunque se bloquee la ejecución de scripts sigue siendo posible la inyección arbitraria de marcado
    También podrían alterar el CSS con una etiqueta <style>, y por ejemplo cambiar el diseño de una página de perfil de PayPal
    uno se pregunta quién querría eso

    • Aun así, podría ser útil cuando quieres permitir que los usuarios escriban Markdown, como en un foro
      puedes añadir una capa extra de defensa limitando otra vez con un sanitizer el HTML generado desde Markdown, permitiendo solo ciertas etiquetas
    • En ese caso debería haberse usado innerHTML no, sino innerText o textContent
      setHTML es un reemplazo para innerHTML
    • Si la configuración por defecto de setHTML() es demasiado estricta o demasiado laxa, el desarrollador puede ofrecer una configuración personalizada para definir directamente qué elementos y atributos HTML se permiten
    • Como incluso solo con CSS pueden aparecer riesgos de seguridad, todavía hay que tener cuidado
      véase este hilo para una discusión relacionada
    • Por ejemplo
      .setHTML("<h1>Hello</h1>", new Sanitizer({}))
      
      así se eliminan todos los elementos
      al final, en el backend todavía hay que sanitizar el nombre de usuario de la forma estándar, y al mostrarlo hay que aplicar escape de HTML
      según RFC 2119, esto es un requisito de nivel “SHOULD”
  • Me alegra que aparezca esta función, pero parece que hará falta tiempo para que el soporte en navegadores se extienda lo suficiente
    Puedes revisar el estado de compatibilidad en Can I use

    • Como otras APIs de navegador, podría tardar años, o si solo apuntas a versiones recientes quizá baste con unos meses
      mientras tanto puede sustituirse con un polyfill
  • El título era un poco sensacionalista
    en realidad también se podría implementar la sanitización con una función que inspeccione la entrada antes de pasarla a innerHTML, ¿no?
    pero este tipo de intentos termina sintiéndose como reinventar la rueda
    además, en Firefox antiguos hacks.mozilla.org ni siquiera abre, y en Pale Moon o SeaMonkey MDN se ve roto
    casi parece que un “cártel de navegadores” quisiera arruinar la web

    • Decir “se puede resolver con una función de validación de entrada” es como decir “el lenguaje C también es memory-safe si no tiene bugs”
      además, es una afirmación que ni siquiera considera el problema de las diferencias entre parsers (parser differential)
  • Si se usa mal, la Sanitizer API puede convertirse en una footgun
    sobre todo hay que tener cuidado al usar el modo “remove”
    yo preferiría usar solo setText y no permitir en absoluto que el usuario agregue HTML

    • Con un Sanitizer basado en lista de permitidos (allowlist), el riesgo se reduce, pero mientras uses setHTML no ocurrirá XSS
    • Pero entonces, ¿qué se hace cuando quien crea la página necesita agregar fragmentos grandes de HTML?
      viendo lo común que es innerHTML, parece difícil excluirlo por completo
    • De hecho, este tipo de API podría ser más peligroso al crear la ilusión de que es “100% seguro”
  • Me impresiona que todos los aspectos del acceso a red estén controlados correctamente, y que ahora la cadena de seguridad se haya movido de confiar en el código a confiar en la configuración del host
    además, los valores por defecto están puestos de forma segura

  • Lo que yo de verdad quiero es un elemento <sandbox> que permita ejecutar código peligroso de forma segura
    no corregir el código peligroso, sino poder correrlo en un entorno aislado
    los iframe tienen la limitación de no fluir junto con el DOM, y en una era de IA y contenido dinámico creciente se necesita encapsulación componible

  • Me encanta el nombre setHTMLUnsafe
    las funciones de seguridad fracasan cuando están diseñadas para que el desarrollador tenga que hacer opt-in
    en cambio, funciona mejor hacer que “la ruta peligrosa se sienta peligrosa”

  • El nombre set_html() es mucho más intuitivo que inner_html
    las APIs de JavaScript están realmente hechas un desastre y algún día deberían ordenarse
    esta discusión se centra en la seguridad, pero cuando se publica una API nueva, el diseño en sí también debería ser limpio

    • Estrictamente hablando, esto es una API del DOM
      las APIs del DOM desde hace mucho tiempo, y todavía hoy, dan la sensación de que “las hizo gente que nunca había diseñado una API”
  • Desarrolladores de los 90:

    SQL("select * from user where name = " + name);
    

    Desarrolladores de los 2020:

    div.innerHTML = "Hello " + user.name;
    
    • Desarrolladores de los 2030:
      "Summarize this email: " + email.contents
      
      La inyección de prompts es solo el mismo problema sobre una tecnología nueva
      no aprendimos nada de los 90