FlawOpen

flawopen.com/XSS en JavaScript/dangerouslySetInnerHTML

¿Es seguro dangerouslySetInnerHTML en React?

Página de referencia
Respuesta breve

Piensa en JSX normal como una impresora de etiquetas: el texto sigue siendo texto. dangerouslySetInnerHTML cambia a una imprenta que interpreta la cadena como HTML. Si contiene contenido controlado por un atacante, el navegador puede tratarlo como marcado activo. Usa este punto solo con HTML deliberadamente confiable o saneado para el contexto HTML exacto.

Por qué JSX normal no necesita esto

RIESGO — entrada de HTML sin procesar
function Comment({ html }) {
  return <p dangerouslySetInnerHTML=
    {{ __html: html }} />;
}
SEGURO — interpolación JSX normal
function Comment({ text }) {
  return <p>{text}</p>;
}

¿Cuándo conviene usar dangerouslySetInnerHTML?

Úsalo solo cuando el producto deba conservar un formato de texto enriquecido restringido que no pueda representarse con hijos React normales. Un CMS, editor o procesador Markdown no es confiable automáticamente: el contenido almacenado y la salida del procesador pueden contener marcado no confiable. Define los elementos y atributos permitidos, sanea con una biblioteca mantenida como DOMPurify y pasa el resultado saneado directamente a este punto.

Uso correcto

Sanear en el límite de renderizado

Sanea justo antes de asignar el valor a dangerouslySetInnerHTML con una biblioteca mantenida como DOMPurify. No uses expresiones regulares como saneador HTML. Evita modificar después la cadena saneada: una transformación posterior puede invalidar las garantías del saneador. Mantén actualizados el saneador y su entorno de análisis.

Limita el marcado permitido

Una lista de bloqueo de etiquetas conocidas es incompleta: el riesgo también puede proceder de atributos, campos con URL, espacios de nombres y del comportamiento del analizador. Elige una lista pequeña de elementos y atributos necesarios para la función y configura el saneador con esa política. Revisa por separado los enlaces y otros atributos con URL según los destinos que permita el producto.

Cómo revisar tu código

grep -rn "dangerouslySetInnerHTML" --include="*.jsx" --include="*.tsx" .
Para cada coincidencia, sigue el valor desde su origen y todas sus transformaciones. Trata las entradas de usuario, el contenido importado y el texto enriquecido almacenado como no confiables; confirma que la política del saneador encaja con el contexto de salida y que ningún paso posterior modifica el resultado saneado.

Preguntas frecuentes

¿La conversión de Markdown es segura automáticamente?

Depende del procesador y de su configuración. Comprueba si acepta HTML sin procesar y si sanea la salida; no supongas que convertir Markdown hace que el HTML sea seguro.

¿Esto también se aplica a v-html de Vue?

Sí. v-html también entrega HTML al navegador sin la interpolación de texto habitual del framework. Trata el valor como un punto de entrada HTML y sanea el contenido no confiable con una política adecuada.

Referencias

Véase también Cross-Site Scripting (XSS, CWE-79): cómo funciona y cómo evitarlo en cada lenguaje — flawopen.com ¿DOMPurify basta para proteger innerHTML? ¿Markdown es seguro frente a XSS? ¿Svelte protege contra XSS por defecto? ¿La carga de SVG implica riesgo de XSS? Riesgo de XSS con Vue v-html WKWebView: ¿HTML no confiable seguro?