flawopen.com/XSS/Renderizado de Markdown
¿Markdown es seguro frente a XSS?
Trata el HTML generado desde Markdown como contenido no confiable. Un parser puede conservar HTML sin procesar porque la sintaxis lo permite; convertir Markdown no sanea la salida. El parser es un traductor que copia el marcado, no un guardia de seguridad.
Dónde está el límite de confianza
La especificación CommonMark indica que el HTML sin procesar con forma de etiqueta se representa sin escaparlo. El comportamiento depende del parser, sus opciones, complementos y el framework. Marked, por ejemplo, advierte que no sanea el HTML generado. La sintaxis Markdown no demuestra que la entrada sea segura; el saneador debe proteger el destino HTML final.
Un flujo de renderizado seguro
const html = marked.parse(userMarkdown); container.innerHTML = html; // la salida no está saneada
import DOMPurify from "dompurify";
const html = marked.parse(userMarkdown);
container.innerHTML = DOMPurify.sanitize(html, {
USE_PROFILES: { html: true }
});
El ejemplo usa el perfil HTML de DOMPurify porque esta vista no necesita SVG ni MathML. Limita las funciones a las que necesita tu producto. No modifiques el marcado saneado ni lo pases por otra biblioteca que transforme HTML antes de insertarlo: eso puede invalidar las garantías. Si no necesitas HTML enriquecido, usa la salida de texto segura del framework. Content Security Policy y Trusted Types son defensas adicionales, no sustitutos del saneamiento.
Revisión para producción
- ✓Fija la versión del parser Markdown y revisa sus opciones de HTML, complementos y URL.
- ✓Sanea el HTML final con una biblioteca de lista permitida mantenida, justo antes del destino HTML.
- ✓Limita etiquetas, atributos y protocolos URL a las funciones necesarias.
- ✓No edites ni vuelvas a analizar el marcado tras sanearlo; vuelve a sanear después de cualquier transformación necesaria.
- ✓Prueba la configuración exacta del parser y el destino de renderizado, y mantén actualizado el saneador.
Preguntas frecuentes
Elimina una función de entrada, pero no garantiza la seguridad. Revisa enlaces, imágenes, extensiones, HTML generado y contexto de inserción; sanea la salida al usarla como HTML.
Evítalo. Los cambios posteriores pueden introducir marcado inseguro o invalidar las decisiones del saneador. Haz las transformaciones primero y sanea al final.
No. Úsalo para fragmentos HTML según su modelo de amenazas, mantenlo actualizado, aplica una política acotada y no reutilices la salida como cadena JavaScript o CSS.
Referencias
- Especificación CommonMark — HTML sin procesar
- Documentación Marked — aviso de seguridad
- DOMPurify — README y uso
- OWASP — prevención de Cross-Site Scripting
- flawopen.com — Cross-Site Scripting