La conversión de Markdown a código HTML presenta un reto de seguridad crítico y a menudo subestimado: la prevención del ataque de **Cross-Site Scripting (XSS)**. Dado que las especificaciones oficiales de Markdown (incluyendo CommonMark y GFM) permiten de forma deliberada incrustar etiquetas HTML en bruto para ampliar las capacidades visuales del lenguaje, un atacante o usuario malintencionado puede inyectar scripts JavaScript ejecutables en un documento sin el debido control.

Si la salida HTML de un parser de Markdown no se desinfecta adecuadamente antes de inyectarse en el DOM activo del navegador, cualquier script malicioso se ejecutará bajo el contexto de seguridad del sitio web de origen. Esto puede resultar en la filtración de tokens almacenados en localStorage, secuestro de sesiones y robo de datos confidenciales de la RAM.

El Dilema de la Sanitización: Los programadores novatos suelen intentar desinfectar el HTML utilizando expresiones regulares (Regex). Sin embargo, la teoría de lenguajes formales y los analistas de seguridad de OWASP afirman que la sintaxis de HTML5 es demasiado compleja y anidada para ser parseada y limpiada de manera robusta usando patrones Regex.

¿Por qué fallan las Expresiones Regulares (Regex) ante XSS?

El filtrado basado en Regex funciona buscando patrones de texto (como la etiqueta <script>) e intentando eliminarlos del string. Esta estrategia es intrínsecamente débil y fácil de eludir debido a las siguientes razones:

  • Atributos de Eventos HTML (Inline Event Handlers): Un atacante no necesita usar la etiqueta <script>. Puede inyectar código malicioso en atributos de elementos legítimos, por ejemplo: <img src="x" onerror="alert(localStorage.getItem('token'))">. Diseñar un Regex para cubrir todos los manejadores de eventos mutables (onload, onerror, onclick, onmouseover, etc.) es propenso a omisiones fatales.
  • Esquemas de URI Ofuscados: Se pueden inyectar scripts en enlaces HTML ordinarios codificando el esquema de la URL: <a href="javascript:alert(1)">Click</a>. Los atacantes también pueden evadir filtros de texto utilizando codificación en base64, saltos de línea y entidades HTML.
  • Múltiples Formas de Renderizado en Navegadores: Los navegadores modernos implementan motores de reparación de HTML tolerantes a errores. Una sintaxis HTML mal formada (como un tag mal cerrado o comillas faltantes) puede eludir una expresión regular rígida pero ejecutarse con éxito al ser analizada por el renderizador del navegador.

La Solución Científica: Sanitización Basada en Árbol DOM con DOMPurify

Para mitigar el riesgo de XSS al 100% en entornos client-side como **Markdify**, se debe emplear un desinfectante basado en DOM real como **DOMPurify** (desarrollado por los investigadores de seguridad de Cure53).

En lugar de procesar el código HTML como un simple string plano, DOMPurify utiliza la API del navegador (DOMParser) para compilar de forma aislada la cadena HTML en un árbol DOM virtual (Document Object Model) inerte. Una vez que el navegador ha parseado y reparado la sintaxis automáticamente, DOMPurify recorre recursivamente todos los nodos del árbol y valida cada elemento y atributo frente a una lista blanca (allowlist) estrictamente definida de etiquetas seguras:

// Arquitectura correcta de renderizado seguro de Markdown en el Cliente:
const rawHtml = window.marked.parse(markdownInput);
const cleanHtml = window.DOMPurify.sanitize(rawHtml, {
  USE_PROFILES: { html: true }, // Solo tags HTML permitidos
  FORBID_TAGS: ['style', 'script', 'iframe', 'object', 'embed'],
  FORBID_ATTR: ['onerror', 'onload', 'onclick']
});
document.getElementById('markdown-preview').innerHTML = cleanHtml;

Cualquier etiqueta sospechosa, atributo no autorizado o esquema no permitido (javascript:, data:) se elimina quirúrgicamente a nivel de nodo DOM, entregando una salida completamente inocua sin alterar el formato ni romper el flujo visual legítimo de las tablas, checklists y citas del documento.

Referencias Oficiales