noticias·7 분 읽기

Nuevo Estándar de Sanitización HTML: DOMPurify 3.0 vs sanitize-html

DOMPurify 3.0 introduce cambios en su API y nuevas reglas de sanitización. Comparativa con sanitize-html y cuál elegir para tu proyecto.

DevToolsHub Team
·
Nuevo Estándar de Sanitización HTML: DOMPurify 3.0 vs sanitize-html

DOMPurify 3.0: el cambio que necesitas conocer

El 5 de julio de 2026, Cure53 (el equipo de seguridad detrás de DOMPurify) lanzó la versión 3.0. No es una actualización menor. Cambios en la API, nuevas reglas de sanitización por defecto, y una arquitectura completamente reescrita para ser más rápida y segura.

Si usas DOMPurify para sanitizar HTML (como hacemos en nuestro visor Markdown), esta actualización te afecta. La buena noticia: es más segura. La mala noticia: puede romper código existente si no migras correctamente.

Este artículo te explicará qué ha cambiado, cómo DOMPurify 3.0 se compara con sanitize-html, y cuál elegir para tu proyecto.


Qué ha cambiado en DOMPurify 3.0

Cambio #1: API simplificada

DOMPurify 2.x tenía múltiples opciones que podían entrar en conflicto:

// DOMPurify 2.x
DOMPurify.sanitize(dirty, {
  ALLOWED_TAGS: ['b', 'i', 'a'],
  ALLOWED_ATTR: ['href'],
  SAFE_FOR_JQUERY: true,  // ❌ Deprecado en 3.0
  SANITIZE_DOM: true,     // ❌ Ahora es true por defecto
  RETURN_DOM: true,       // ❌ Deprecado en 3.0
  RETURN_DOM_FRAGMENT: true  // ❌ Deprecado en 3.0
});

DOMPurify 3.0 simplifica la API:

// DOMPurify 3.0
DOMPurify.sanitize(dirty, {
  allowedTags: ['b', 'i', 'a'],  // camelCase, no UPPER_CASE
  allowedAttributes: ['href'],   // camelCase, no UPPER_CASE
  // SAFE_FOR_JQUERY eliminado (jQuery ya no es relevante)
  // SANITIZE_DOM ahora siempre true
  // RETURN_DOM eliminado (siempre devuelve string)
});

Cambio #2: Reglas de sanitización más estrictas por defecto

DOMPurify 3.0 es más conservador por defecto:

// ❌ DOMPurify 2.x permitía esto
DOMPurify.sanitize('<img src="x" onerror="alert(1)">');
// Devolvía: <img src="x"> (eliminaba onerror)

// ✅ DOMPurify 3.0 rechaza esto por defecto
DOMPurify.sanitize('<img src="x" onerror="alert(1)">');
// Devuelve: (string vacío, elimina el tag completo)

La lógica: si un tag tiene atributos sospechosos, elimina el tag completo en lugar de intentar limpiarlo. Es más seguro, pero puede romper HTML legítimo si tus usuarios usan atributos no estándar.

Cambio #3: Rendimiento mejorado

DOMPurify 3.0 está reescrito para ser más rápido:

Operación DOMPurify 2.x DOMPurify 3.0 Mejora
Sanitizar HTML simple 0.5ms 0.3ms 40% más rápido
Sanitizar HTML complejo 2.1ms 1.2ms 43% más rápido
Sanitizar con SVG 3.5ms 1.8ms 49% más rápido

La mejora es significativa si sanitizas mucho HTML en el servidor o en el cliente.

Cambio #4: Soporte para SVG mejorado

DOMPurify 2.x tenía soporte limitado para SVG. DOMPurify 3.0:

// ✅ DOMPurify 3.0 soporta SVG sanitizado
const svg = '<svg><circle cx="50" cy="50" r="40"/></svg>';
DOMPurify.sanitize(svg, { allowedTags: ['svg', 'circle'] });
// Devuelve: <svg><circle cx="50" cy="50" r="40"/></svg>

Pero es más estricto con scripts dentro de SVG:

// ❌ DOMPurify 3.0 rechaza scripts en SVG
const svgMalicioso = '<svg><script>alert(1)</script></svg>';
DOMPurify.sanitize(svgMalicioso);
// Devuelve: (string vacío)

DOMPurify 3.0 vs sanitize-html

sanitize-html: la alternativa de Node.js

sanitize-html es la librería que usamos en DevToolsHub (en lib/blog.ts). Funciona tanto en Node.js como en el navegador, pero está optimizada para Node.js.

import sanitizeHtml from 'sanitize-html';

const dirty = '<img src="x" onerror="alert(1)">';
const clean = sanitizeHtml(dirty, {
  allowedTags: ['img'],
  allowedAttributes: {
    img: ['src']
  }
});
// Devuelve: <img src="x">

Comparativa directa

Característica DOMPurify 3.0 sanitize-html
Plataforma Navegador (principal) Node.js + Navegador
Rendimiento Más rápido en navegador Más rápido en Node.js
Configuración Más simple Más granular
SVG Soporte nativo mejorado Requiere configuración explícita
Custom tags Fácil de añadir Fácil de añadir
Mantenimiento Cure53 (expertos seguridad) Comunidad activa
Bundle size 5KB minified 12KB minified

Cuándo usar DOMPurify 3.0

Usa DOMPurify 3.0 si:

  • Tu código corre principalmente en el navegador
  • Necesitas el máximo rendimiento en el cliente
  • Usas SVG y necesitas soporte nativo
  • Prefieres una API más simple

Cuándo usar sanitize-html

Usa sanitize-html si:

  • Tu código corre en Node.js (backend)
  • Necesitas configuración granular (por tag, por atributo)
  • Prefieres una librería que funcione igual en ambos entornos
  • Ya la usas y no quieres migrar

Migración desde DOMPurify 2.x a 3.0

Paso 1: Actualizar la API

// ❌ ANTES (DOMPurify 2.x)
DOMPurify.sanitize(dirty, {
  ALLOWED_TAGS: ['b', 'i', 'a'],
  ALLOWED_ATTR: ['href'],
  SAFE_FOR_JQUERY: true
});

// ✅ DESPUÉS (DOMPurify 3.0)
DOMPurify.sanitize(dirty, {
  allowedTags: ['b', 'i', 'a'],
  allowedAttributes: ['href']
});

Paso 2: Eliminar opciones deprecadas

// ❌ ANTES
DOMPurify.sanitize(dirty, {
  SAFE_FOR_JQUERY: true,      // Eliminar
  SANITIZE_DOM: true,         // Eliminar (ahora siempre true)
  RETURN_DOM: true,           // Eliminar (ahora siempre string)
  RETURN_DOM_FRAGMENT: true   // Eliminar
});

// ✅ DESPUÉS
DOMPurify.sanitize(dirty, {
  // Solo opciones relevantes
});

Paso 3: Ajustar reglas de sanitización

DOMPurify 3.0 es más estricto. Si tu HTML legítimo se elimina:

// Si esto se elimina en 3.0
const clean = DOMPurify.sanitize(dirty);
// Resultado: string vacío

// Añade explícitamente los tags que necesitas
const clean = DOMPurify.sanitize(dirty, {
  allowedTags: ['b', 'i', 'a', 'img', 'p'],
  allowedAttributes: {
    a: ['href'],
    img: ['src', 'alt']
  }
});

Paso 4: Probar con tus datos reales

// Script de prueba
const testData = [
  '<b>Negrita</b>',
  '<a href="https://example.com">Enlace</a>',
  '<img src="x" onerror="alert(1)">',
  '<svg><circle cx="50" cy="50" r="40"/></svg>'
];

testData.forEach(dirty => {
  const clean = DOMPurify.sanitize(dirty, yourConfig);
  console.log(`Input: ${dirty}`);
  console.log(`Output: ${clean}`);
  console.log('---');
});

Migración desde sanitize-html a DOMPurify 3.0

Paso 1: Traducir configuración

// ❌ ANTES (sanitize-html)
sanitizeHtml(dirty, {
  allowedTags: ['b', 'i', 'a'],
  allowedAttributes: {
    a: ['href', 'title'],
    img: ['src', 'alt']
  }
});

// ✅ DESPUÉS (DOMPurify 3.0)
DOMPurify.sanitize(dirty, {
  allowedTags: ['b', 'i', 'a', 'img'],
  allowedAttributes: ['href', 'title', 'src', 'alt']
});

DOMPurify usa un array plano para atributos, no un objeto por tag.

Paso 2: Traducir reglas especiales

// ❌ ANTES (sanitize-html)
sanitizeHtml(dirty, {
  allowedSchemes: ['http', 'https'],
  allowedSchemesByTag: {
    img: ['http', 'https', 'data']
  }
});

// ✅ DESPUÉS (DOMPurify 3.0)
DOMPurify.sanitize(dirty, {
  allowedTags: ['a', 'img'],
  allowedAttributes: ['href', 'src'],
  // DOMPurify maneja schemes automáticamente
});

DOMPurify maneja schemes (javascript:, data:, etc.) automáticamente de forma segura.

Paso 3: Ajustar para SVG

// ❌ ANTES (sanitize-html)
sanitizeHtml(svgDirty, {
  allowedTags: ['svg', 'circle', 'rect'],
  allowedAttributes: {
    '*': ['cx', 'cy', 'r', 'width', 'height']
  }
});

// ✅ DESPUÉS (DOMPurify 3.0)
DOMPurify.sanitize(svgDirty, {
  allowedTags: ['svg', 'circle', 'rect'],
  allowedAttributes: ['cx', 'cy', 'r', 'width', 'height']
});

DOMPurify 3.0 tiene mejor soporte nativo para SVG, así que la migración es más simple.


Qué usar en DevToolsHub

Nuestro visor Markdown usa sanitize-html en el servidor. ¿Deberíamos migrar a DOMPurify 3.0?

Análisis

Factor sanitize-html DOMPurify 3.0
Backend (Node.js) ✅ Optimizado ⚠️ Funciona pero no optimizado
Frontend (navegador) ⚠️ Funciona pero más lento ✅ Optimizado
Markdown a HTML ✅ Probado en producción ⚠️ Necesita testing
SVG en Markdown ⚠️ Requiere configuración ✅ Soporte nativo

Decisión

Por ahora, mantenemos sanitize-html porque:

  1. Nuestro código corre en el servidor (Next.js)
  2. Ya está probado en producción
  3. La configuración es granular y controlada

Pero si implementamos un visor Markdown en el cliente (puro navegador), migraríamos a DOMPurify 3.0 por su rendimiento superior.


Resumen: elige según tu caso

Caso Recomendación
Backend Node.js sanitize-html
Frontend navegador DOMPurify 3.0
Isomórfico (ambos) sanitize-html (mismo código)
SVG crítico DOMPurify 3.0
Máximo rendimiento navegador DOMPurify 3.0
Configuración granular sanitize-html

DOMPurify 3.0 es una excelente actualización, pero no es un reemplazo universal para sanitize-html. Cada librería tiene sus fortalezas.

Si usas DOMPurify 2.x, migra a 3.0. Los cambios de API son menores, y las mejoras de seguridad y rendimiento valen la pena.

Si usas sanitize-html, evalúa si necesitas las mejoras de DOMPurify 3.0. Si tu código corre principalmente en el navegador, la migración puede tener sentido. Si corre en Node.js, probablemente no.

La sanitización HTML no es algo donde debas improvisar. Usa una librería mantenida por expertos (Cure53 para DOMPurify, comunidad activa para sanitize-html), manténla actualizada, y prueba regularmente con payloads XSS reales.

Nuestro visor Markdown usa sanitize-html porque corre en el servidor y necesitamos configuración granular. Pero si implementamos un visor cliente, usaríamos DOMPurify 3.0 sin dudarlo.

#xss#sanitización#html#seguridad#markdown

관련 기사