Volver a actualizaciones
Nuevo releaseSep 7, 2026

DOMPurify v3.4.15

DOMPurify: un sanitizador XSS exclusivo para DOM, súper rápido y ultra tolerante, para HTML, MathML y SVG. DOMPurify funciona con una configuración segura por defecto, pero ofrece mucha configurabilidad y hooks. Demo:

Compartir

DOMPurify

npm License Downloads dependents npm package minimized gzipped size (select exports) Cloudback

OpenSSF Best Practices Build & Test OpenSSF Scorecard Socket Badge snyk.io package health

DOMPurify es un sanitizador XSS exclusivo de DOM, ultrarrápido y extremadamente tolerante para HTML, MathML y SVG.

También es muy sencillo de usar y de empezar a trabajar con él. DOMPurify fue iniciado en febrero de 2014 y, mientras tanto, ha alcanzado la versión v3.4.15.

DOMPurify se ejecuta como JavaScript y funciona en todos los navegadores modernos (Safari (10+), Opera (15+), Edge, Firefox y Chrome, así como prácticamente cualquier otro que use Blink, Gecko o WebKit). No se rompe en MSIE ni en otros navegadores heredados. Simplemente no hace nada.

Ten en cuenta que DOMPurify v2.5.9 es la última versión compatible con MSIE. Para actualizaciones de seguridad importantes compatibles con MSIE, usa la rama 2.x.

Nuestras pruebas automatizadas cubren 9 combinaciones de navegador/SO en los motores actuales (Chromium, Firefox y WebKit en Ubuntu, macOS y Windows) en cada push, y una matriz separada vuelve a ejecutar el conjunto en instantáneas de motores más antiguos (hasta aproximadamente Chromium 110, Firefox 108 y WebKit 16.4, de unos tres años de antigüedad) para que también se detecten regresiones en navegadores desactualizados. También ejecutamos Node.js v20, v22, v24, v25 y v26 con DOMPurify en jsdom. Se sabe que las versiones más antiguas de Node también funcionan, pero... no hay garantías.

DOMPurify está escrito por personas de seguridad con amplia experiencia en ataques web y XSS. No temas. Para más detalles, te recomendamos leer también nuestros Objetivos de Seguridad y Modelo de Amenazas. Por favor, léelo. En serio. Y si disfrutas de los detalles escabrosos, la página de Clases de Ataque e Historial de Bypass cataloga los trucos de mutación de parser, namespaces, clobbering y plantillas contra los que DOMPurify se defiende.

El proyecto DOMPurify inspiró la creación de la API de Sanitización HTML, que ya se está implementando en muchos navegadores. La misma capacidad ahora se está estandarizando directamente en la especificación HTML de WHATWG.

Tabla de contenidos

¿Qué hace?

DOMPurify sanitiza HTML y previene ataques XSS. Puedes alimentar a DOMPurify, por ejemplo, con una cadena llena de HTML sucio y devolverá una cadena (a menos que se configure de otro modo) con HTML limpio. DOMPurify eliminará todo lo que contenga HTML peligroso y, de este modo, prevendrá ataques XSS y otras cosas desagradables. También es increíblemente rápido. Usamos las tecnologías que el navegador proporciona y las convertimos en un filtro XSS. Cuanto más rápido sea tu navegador, más rápido será DOMPurify.

¿Cómo lo uso?

Es fácil. Solo incluye DOMPurify en tu sitio web.

Usando la versión sin minificar (con source-map disponible)```html

### Usando la versión de producción minificada y probada (source-map disponible)```html
<script type="text/javascript" src="dist/purify.min.js"></script>

Después puedes sanitizar cadenas ejecutando el siguiente código:```js const clean = DOMPurify.sanitize(dirty);

O quizá esto, si te encanta trabajar con Angular o similares:```js
import DOMPurify from 'dompurify';

const clean = DOMPurify.sanitize('<b>hello there</b>');

El HTML resultante puede escribirse en un elemento del DOM mediante innerHTML o en el DOM usando document.write(). Eso depende completamente de ti. Ten en cuenta que, por defecto, permitimos HTML, SVG y MathML. Si solo necesitas HTML, que podría ser un caso de uso muy común, también puedes configurarlo fácilmente:```js const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });

### ¿Hay algún riesgo de dispararse en el pie?

Bueno, ten en cuenta que si _primero_ sanitizas el HTML y luego lo modificas _después_, podrías fácilmente **anular los efectos de la sanitización**. Si pasas el marcado sanitizado a otra librería _después_ de la sanitización, asegúrate de que esa librería no manipule el HTML por su cuenta. Consulta los [Objetivos de Seguridad y el Modelo de Amenazas](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model) para conocer recetas de uso seguro y las etiquetas/atributos que vale la pena reconsiderar, y las [Clases de Ataque e Historial de Bypass](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History) para entender por qué el post-procesamiento y el cambio del contexto del marcado anulan la sanitización.

### Vale, tiene sentido, sigamos adelante

Después de sanitizar tu marcado, también puedes echar un vistazo a la propiedad `DOMPurify.removed` y averiguar qué elementos y atributos fueron descartados. Por favor, **no uses** esta propiedad para tomar decisiones críticas de seguridad. Es solo una pequeña ayuda para mentes curiosas.

### Ejecutar DOMPurify en el servidor

DOMPurify técnicamente también funciona en el lado del servidor con Node.js. Nuestro soporte busca seguir el [ciclo de versiones de Node.js](https://nodejs.org/en/about/previous-releases).

Ejecutar DOMPurify en el servidor requiere que haya un DOM presente, lo cual probablemente no sea una sorpresa. Normalmente, [jsdom](https://github.com/jsdom/jsdom) es la herramienta de elección y **recomendamos encarecidamente** usar la última versión de _jsdom_.

¿Por qué? Porque se sabe que las versiones antiguas de _jsdom_ tienen errores que resultan en XSS _incluso si_ DOMPurify hace todo 100% correctamente. Hay **vectores de ataque conocidos** en, por ejemplo, _jsdom v19.0.0_ que están corregidos en _jsdom v20.0.0_ — y realmente recomendamos mantener _jsdom_ actualizado por eso.

Ten en cuenta también que existen herramientas como [happy-dom](https://github.com/capricorn86/happy-dom), pero **no se consideran seguras** en este momento. Combinar DOMPurify con _happy-dom_ no se recomienda actualmente y probablemente conducirá a XSS. Para conocer el contexto de por qué el DOM del lado del servidor que elijas forma parte de tu base de confianza informática, consulta las [Clases de Ataque e Historial de Bypass](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History).

Aparte de eso, puedes usar DOMPurify en el servidor sin problema. Probablemente. Esto realmente depende de _jsdom_ o del DOM que utilices en el lado del servidor. Si puedes vivir con eso, así es como lo haces funcionar:```bash
npm install dompurify
npm install jsdom

Para jsdom (por favor, usa una versión actualizada), esto debería funcionar:```js const createDOMPurify = require('dompurify'); const { JSDOM } = require('jsdom');

const window = new JSDOM('').window; const DOMPurify = createDOMPurify(window); const clean = DOMPurify.sanitize('hello there');

O incluso esto, si prefieres trabajar con imports:```js
import { JSDOM } from 'jsdom';
import DOMPurify from 'dompurify';

const window = new JSDOM('').window;
const purify = DOMPurify(window);
const clean = purify.sanitize('<b>hello there</b>');

Si tienes problemas para hacerlo funcionar en tu configuración específica, considera revisar el increíble proyecto isomorphic-dompurify, que resuelve muchos de los problemas con los que la gente podría encontrarse.```bash npm install isomorphic-dompurify

I need the actual content of chunk 19 to translate it. Please provide the Markdown text you want translated from English to Spanish.```js
import DOMPurify from 'isomorphic-dompurify';

const clean = DOMPurify.sanitize('<s>hello</s>');

¿Hay una demo?

¡Por supuesto que hay una demo! Juega con DOMPurify

¿Y si encuentro un fallo de seguridad?

En primer lugar, contacta con nosotros de inmediato por correo electrónico para que podamos trabajar en una solución. Clave PGP

Además, ¡probablemente califiques para un programa de recompensas por errores! La excelente gente de Fastmail usa DOMPurify para sus servicios y añadió nuestra librería al alcance de su programa de recompensas. Así que, si encuentras una forma de evadir o debilitar DOMPurify, echa también un vistazo a su sitio web y a la información sobre recompensas por errores.

¿Algunas muestras de purificación, por favor?

¿Cómo se ve el marcado purificado? Bueno, la demo lo muestra con un buen montón de elementos desagradables. ¡Pero también mostremos algunos ejemplos más pequeños!```js DOMPurify.sanitize(''); // becomes DOMPurify.sanitize('<g/onload=alert(2)//

'); // becomes DOMPurify.sanitize('

abcdef

'); // becomes

abc

DOMPurify.sanitize('<mi//xlink:href="data:x,">'); // becomes DOMPurify.sanitize(''); // becomes
HELLO
HELLO
DOMPurify.sanitize('
  • <A HREF=//google.com>click
'); // becomes

Estos son solo una muestra. Para ver la taxonomía completa de clases de ataque de las que provienen estas muestras — XSS por mutación, confusión de espacios de nombres, DOM clobbering, fugas de rawtext y más — consulta [Attack Classes & Bypass History](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History).

## ¿Qué es compatible?

DOMPurify actualmente es compatible con HTML5, SVG y MathML. DOMPurify permite por defecto CSS y atributos de datos personalizados de HTML. DOMPurify también es compatible con Shadow DOM — y sanea plantillas DOM de forma recursiva. DOMPurify también te permite sanear HTML para usarlo con las API `$()` y `elm.html()` de jQuery sin ningún problema conocido. Para ver el conjunto exacto de elementos y atributos permitidos por defecto, consulta la página wiki [Default TAGs & ATTRIBUTEs allow-list & blocklist](https://github.com/cure53/DOMPurify/wiki/Default-TAGs-ATTRIBUTEs-allow-list-&-blocklist).

## ¿Qué pasa con navegadores heredados como Internet Explorer?

DOMPurify no hace nada en absoluto. Simplemente devuelve exactamente la cadena que le proporcionaste. DOMPurify expone una propiedad llamada `isSupported`, que te indica si podrá realizar su trabajo, para que puedas idear tu propio plan de respaldo.

## ¿Qué pasa con DOMPurify y Trusted Types?

En la versión 1.0.9, se añadió a DOMPurify soporte para la [Trusted Types API](https://github.com/w3c/webappsec-trusted-types) ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API)).
En la versión 2.0.0, se añadió una bandera de configuración para controlar el comportamiento de DOMPurify al respecto.

Cuando se usa `DOMPurify.sanitize` en un entorno donde la Trusted Types API está disponible y `RETURN_TRUSTED_TYPE` está establecido en `true`, intenta devolver un valor `TrustedHTML` en lugar de una cadena (el comportamiento para las opciones de configuración `RETURN_DOM` y `RETURN_DOM_FRAGMENT` no cambia).

Ten en cuenta que para crear una política en `trustedTypes` usando DOMPurify, se requiere `RETURN_TRUSTED_TYPE: false`, ya que `createHTML` espera una cadena normal, no `TrustedHTML`. El ejemplo siguiente lo muestra.```js
window.trustedTypes.createPolicy('default', {
  createHTML: (to_escape) =>
    DOMPurify.sanitize(to_escape, { RETURN_TRUSTED_TYPE: false }),
});

Cuando no se suministra una TRUSTED_TYPES_POLICY, DOMPurify intenta crear su propia política interna de Trusted Types llamada dompurify. Si tu página ya define su propia política junto con una CSP estricta (por ejemplo, trusted-types my-organization) que no permite una política llamada dompurify, este intento es bloqueado por el navegador y registra una advertencia de TrustedTypes policy dompurify could not be created. junto con una violación de CSP.

Para evitar que DOMPurify cree su política de respaldo interna, pasa TRUSTED_TYPES_POLICY: null. Esta es la opción correcta cuando llamas a DOMPurify.sanitize desde dentro del createHTML de tu propia política, y significa que no tienes que añadir dompurify a la lista de permitidos de trusted-types de tu CSP.```js window.trustedTypes.createPolicy('my-organization', { createHTML: (input) => DOMPurify.sanitize(input, { TRUSTED_TYPES_POLICY: null }), });

No **le** pases tu propia política de envoltura de vuelta a DOMPurify como su `TRUSTED_TYPES_POLICY` (por ejemplo, mediante `DOMPurify.setConfig({ TRUSTED_TYPES_POLICY: myPolicy })`) cuando el `createHTML` de esa política ya llama a `DOMPurify.sanitize`. Eso es circular por definición: sanitizar llamaría a la política, que sanitiza llamando a DOMPurify de nuevo, y DOMPurify lanzará un `TypeError` descriptivo para evitar la recursión infinita. Tu propia política debería llamar a DOMPurify; DOMPurify no debería configurarse para llamar a tu política.

Si quieres que este patrón de política `default` se aplique automáticamente en toda una página, de modo que cada sumidero HTML quede sanitizado, incluido el código heredado, los widgets de terceros y las miles de asignaciones `innerHTML` que no puedes encontrar o reescribir fácilmente, echa un vistazo a [DOMFortify](https://github.com/cure53/DOMFortify). Instala exactamente una política `default` de Trusted Types respaldada por DOMPurify y rechaza de plano los sumideros de scripts (`eval`, `script.src`, ...). Es deliberadamente un proyecto separado: DOMPurify sigue siendo un sanitizador enfocado, y DOMFortify maneja la capa de aplicación a nivel de documento que está intencionalmente fuera del alcance de DOMPurify.

## ¿Puedo configurar DOMPurify?

Sí. Los valores de configuración predeterminados incluidos ya son bastante buenos, pero por supuesto puedes sobrescribirlos. Revisa la carpeta [`/demos`](https://github.com/cure53/DOMPurify/tree/main/demos) para ver varios ejemplos de cómo puedes [personalizar DOMPurify](https://github.com/cure53/DOMPurify/tree/main/demos#what-is-this).

Antes de ampliar la lista de permitidos (`ADD_TAGS`, `ADD_ATTR`, `CUSTOM_ELEMENT_HANDLING`, ...) o relajar un valor predeterminado, vale la pena revisar las [etiquetas y atributos que deberías pensar dos veces](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model#dangerous-tags-and-attributes-think-twice-before-allow-listing): algunos son peligrosos de maneras no evidentes.

### Configuración general```js
// strip {{ ... }}, ${ ... } and <% ... %> to make output safe for template systems
// be careful please, this mode is not recommended for production usage.
// allowing template parsing in user-controlled HTML is not advised at all.
// only use this mode if there is really no alternative.
const clean = DOMPurify.sanitize(dirty, { SAFE_FOR_TEMPLATES: true });

// change how e.g. comments containing risky HTML characters are treated.
// be very careful, this setting should only be set to `false` if you really only handle
// HTML and nothing else, no SVG, MathML or the like.
// Otherwise, changing from `true` to `false` will lead to XSS in this or some other way.
const clean = DOMPurify.sanitize(dirty, { SAFE_FOR_XML: false });

Controla nuestras listas de permitidos y bloqueados```js

// allow only elements, very strict const clean = DOMPurify.sanitize(dirty, { ALLOWED_TAGS: ['b'] });

// allow only and with style attributes const clean = DOMPurify.sanitize(dirty, { ALLOWED_TAGS: ['b', 'q'], ALLOWED_ATTR: ['style'], });

// allow all safe HTML elements but neither SVG nor MathML // note that the USE_PROFILES setting will override the ALLOWED_TAGS setting // so don't use them together const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });

// allow all safe SVG elements and SVG Filters, no HTML or MathML const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { svg: true, svgFilters: true }, });

// allow all safe MathML elements and SVG, but no SVG Filters const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { mathMl: true, svg: true }, });

// change the default namespace from HTML to something different const clean = DOMPurify.sanitize(dirty, { NAMESPACE: 'http://www.w3.org/2000/svg', });

// leave all safe HTML as it is and add elements to block-list const clean = DOMPurify.sanitize(dirty, { FORBID_TAGS: ['style'] });

// leave all safe HTML as it is and add style attributes to block-list const clean = DOMPurify.sanitize(dirty, { FORBID_ATTR: ['style'] });

// extend the existing array of allowed tags and add to allow-list const clean = DOMPurify.sanitize(dirty, { ADD_TAGS: ['my-tag'] });

// extend the existing array of allowed attributes and add my-attr to allow-list const clean = DOMPurify.sanitize(dirty, { ADD_ATTR: ['my-attr'] });

// use functions to control which additional tags and attributes are allowed const allowlist = { one: ['attribute-one'], two: ['attribute-two'], }; const clean = DOMPurify.sanitize( '', { ADD_TAGS: (tagName) => { return Object.keys(allowlist).includes(tagName); }, ADD_ATTR: (attributeName, tagName) => { return allowlist[tagName]?.includes(attributeName) || false; }, } ); //

// prohibit ARIA attributes, leave other safe HTML as is (default is true) const clean = DOMPurify.sanitize(dirty, { ALLOW_ARIA_ATTR: false });

// prohibit HTML5 data attributes, leave other safe HTML as is (default is true) const clean = DOMPurify.sanitize(dirty, { ALLOW_DATA_ATTR: false });

### Comportamiento de control relacionado con los Custom Elements```js
// DOMPurify allows to define rules for Custom Elements. When using the CUSTOM_ELEMENT_HANDLING
// literal, it is possible to define exactly what elements you wish to allow (by default, none are allowed).
//
// The same goes for their attributes. By default, the built-in or configured allow.list is used.
//
// You can use a RegExp literal to specify what is allowed or a predicate, examples for both can be seen below.
// When using a predicate function for attributeNameCheck, it can optionally receive the tagName as a second parameter
// for more granular control over which attributes are allowed for specific elements.
// The default values are very restrictive to prevent accidental XSS bypasses. Handle with great care!

const clean = DOMPurify.sanitize(
  '<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
  {
    CUSTOM_ELEMENT_HANDLING: {
      tagNameCheck: null, // no custom elements are allowed
      attributeNameCheck: null, // default / standard attribute allow-list is used
      allowCustomizedBuiltInElements: false, // no customized built-ins allowed
    },
  }
); // <div is=""></div>

const clean = DOMPurify.sanitize(
  '<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
  {
    CUSTOM_ELEMENT_HANDLING: {
      tagNameCheck: /^foo-/, // allow all tags starting with "foo-"
      attributeNameCheck: /baz/, // allow all attributes containing "baz"
      allowCustomizedBuiltInElements: true, // customized built-ins are allowed
    },
  }
); // <foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>

const clean = DOMPurify.sanitize(
  '<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
  {
    CUSTOM_ELEMENT_HANDLING: {
      tagNameCheck: (tagName) => tagName.match(/^foo-/), // allow all tags starting with "foo-"
      attributeNameCheck: (attr) => attr.match(/baz/), // allow all containing "baz"
      allowCustomizedBuiltInElements: true, // allow customized built-ins
    },
  }
); // <foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>

// Example with attributeNameCheck receiving tagName as a second parameter
const clean = DOMPurify.sanitize(
  '<element-one attribute-one="1" attribute-two="2"></element-one><element-two attribute-one="1" attribute-two="2"></element-two>',
  {
    CUSTOM_ELEMENT_HANDLING: {
      tagNameCheck: (tagName) => tagName.match(/^element-(one|two)$/),
      attributeNameCheck: (attr, tagName) => {
        if (tagName === 'element-one') {
          return ['attribute-one'].includes(attr);
        } else if (tagName === 'element-two') {
          return ['attribute-two'].includes(attr);
        } else {
          return false;
        }
      },
      allowCustomizedBuiltInElements: false,
    },
  }
); // <element-one attribute-one="1"></element-one><element-two attribute-two="2"></element-two>

Comportamiento de control relacionado con los valores de URI```js

// extend the existing array of elements that can use Data URIs const clean = DOMPurify.sanitize(dirty, { ADD_DATA_URI_TAGS: ['a', 'area'] });

// extend the existing array of elements that are safe for URI-like values (be careful, XSS risk) const clean = DOMPurify.sanitize(dirty, { ADD_URI_SAFE_ATTR: ['my-attr'] });

### Control de valores de atributos permitidos```js
// allow external protocol handlers in URL attributes (default is false, be careful, XSS risk)
// by default only http, https, ftp, ftps, tel, mailto, callto, sms, cid, xmpp and matrix are allowed.
const clean = DOMPurify.sanitize(dirty, { ALLOW_UNKNOWN_PROTOCOLS: true });

// allow specific protocol handlers in URL attributes via regex (default is false, be careful, XSS risk)
// by default only (protocol-)relative URLs, http, https, ftp, ftps, tel, mailto, callto, sms, cid, xmpp and matrix are allowed.
// Default RegExp: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
const clean = DOMPurify.sanitize(dirty, {
  ALLOWED_URI_REGEXP:
    /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,
});

Influir en el tipo de retorno```js

// return a DOM HTMLBodyElement instead of an HTML string (default is false) const clean = DOMPurify.sanitize(dirty, { RETURN_DOM: true });

// return a DOM DocumentFragment instead of an HTML string (default is false) const clean = DOMPurify.sanitize(dirty, { RETURN_DOM_FRAGMENT: true });

// use the RETURN_TRUSTED_TYPE flag to turn on Trusted Types support if available const clean = DOMPurify.sanitize(dirty, { RETURN_TRUSTED_TYPE: true }); // will return a TrustedHTML object instead of a string if possible

// use a provided Trusted Types policy const clean = DOMPurify.sanitize(dirty, { // supplied policy must define createHTML and createScriptURL TRUSTED_TYPES_POLICY: trustedTypes.createPolicy('dompurify', { createHTML(s) { return s; }, createScriptURL(s) { return s; }, }), });

// opt out of DOMPurify's internal dompurify Trusted Types policy entirely // (useful when your CSP trusted-types allowlist does not include dompurify) const clean = DOMPurify.sanitize(dirty, { TRUSTED_TYPES_POLICY: null });

### Influencia en cómo saneamos```js
// return entire document including <html> tags (default is false)
const clean = DOMPurify.sanitize(dirty, { WHOLE_DOCUMENT: true });

// disable DOM Clobbering protection on output (default is true, handle with care, minor XSS risks here)
const clean = DOMPurify.sanitize(dirty, { SANITIZE_DOM: false });

// enforce strict DOM Clobbering protection via namespace isolation (default is false)
// when enabled, isolates the namespace of named properties (i.e., `id` and `name` attributes)
// from JS variables by prefixing them with the string `user-content-`
const clean = DOMPurify.sanitize(dirty, { SANITIZE_NAMED_PROPS: true });

// keep an element's content when the element is removed (default is true)
const clean = DOMPurify.sanitize(dirty, { KEEP_CONTENT: false });

// glue elements like style, script or others to document.body and prevent unintuitive browser behavior in several edge-cases (default is false)
const clean = DOMPurify.sanitize(dirty, { FORCE_BODY: true });

// remove all <a> elements under <p> elements that are removed
const clean = DOMPurify.sanitize(dirty, {
  FORBID_CONTENTS: ['a'],
  FORBID_TAGS: ['p'],
});

// extend the default FORBID_CONTENTS list to also remove <a> elements under <p> elements
const clean = DOMPurify.sanitize(dirty, {
  ADD_FORBID_CONTENTS: ['a'],
  FORBID_TAGS: ['p'],
});

// change the parser type so sanitized data is treated as XML and not as HTML, which is the default
const clean = DOMPurify.sanitize(dirty, {
  PARSER_MEDIA_TYPE: 'application/xhtml+xml',
});

Influencia sobre dónde saneamos```js

// use the IN_PLACE mode to sanitize a node "in place", which is much faster depending on how you use DOMPurify const dirty = document.createElement('a'); dirty.setAttribute('href', 'javascript:alert(1)');

const clean = DOMPurify.sanitize(dirty, { IN_PLACE: true }); // see https://github.com/cure53/DOMPurify/issues/288 for more info

Hay incluso [más ejemplos aquí](https://github.com/cure53/DOMPurify/tree/main/demos#what-is-this), que muestran cómo puedes ejecutar, personalizar y configurar DOMPurify para adaptarlo a tus necesidades.

## Configuración persistente

En lugar de pasar repetidamente la misma configuración a `DOMPurify.sanitize`, puedes usar el método `DOMPurify.setConfig`. Tu configuración persistirá hasta tu siguiente llamada a `DOMPurify.setConfig`, o hasta que invoques `DOMPurify.clearConfig` para restablecerla. Recuerda que solo hay una configuración activa, lo que significa que una vez establecida, todos los parámetros de configuración adicionales pasados a `DOMPurify.sanitize` se ignoran.

## Hooks

DOMPurify te permite ampliar su funcionalidad adjuntando una o más funciones con el método `DOMPurify.addHook` a uno de los siguientes hooks:

- `beforeSanitizeElements`
- `uponSanitizeElement` (sin 's' - se llama para cada elemento)
- `afterSanitizeElements`
- `beforeSanitizeAttributes`
- `uponSanitizeAttribute`
- `afterSanitizeAttributes`
- `beforeSanitizeShadowDOM`
- `uponSanitizeShadowNode`
- `afterSanitizeShadowDOM`

Pasa el nodo DOM actualmente procesado, cuando sea necesario un literal con datos verificados de nodo y atributo, y la configuración de DOMPurify a la función de devolución de llamada. Echa un vistazo a la [demo del hook MentalJS](https://github.com/cure53/DOMPurify/blob/main/demos/hooks-mentaljs-demo.html) para ver cómo se puede usar la API de forma adecuada.

_Ejemplo_:```js
DOMPurify.addHook(
  'uponSanitizeAttribute',
  function (currentNode, hookEvent, config) {
    // Do something with the current node
    // You can also mutate hookEvent for current node (i.e. set hookEvent.forceKeepAttr = true)
    // For other than 'uponSanitizeAttribute' hook types hookEvent equals to null
  }
);

Una nota sobre cómo llamar a sanitize() desde un hook

DOMPurify.sanitize() no es reentrante. Por favor, no lo llames desde dentro de un hook, ni desde un callback de configuración como CUSTOM_ELEMENT_HANDLING.tagNameCheck o attributeNameCheck. Esos callbacks se ejecutan en medio de un pase de sanitización activo.

Una llamada anidada a sanitize() vuelve a leer la configuración que se le entrega y, al hacerlo, reemplaza la configuración que el pase externo todavía está usando. El resto del documento externo se sanitiza entonces contra la configuración de la llamada anidada en lugar de la tuya. Dado que la llamada anidada normalmente se ejecuta con la configuración predeterminada, una lista de permitidos estricta de ALLOWED_TAGS puede ampliarse silenciosamente de vuelta a la predeterminada a mitad de un documento, sin error ni advertencia.

Si necesitas sanitizar marcado anidado, por ejemplo un fragmento HTML contenido dentro de un valor de atributo, tienes dos opciones seguras. O bien estableces tu configuración una vez con DOMPurify.setConfig en lugar de pasarla por llamada, ya que una configuración persistente es compartida por la llamada anidada y permanece en vigor durante todo el pase; o bien recopilas los fragmentos durante el hook y los sanitizas con una llamada separada a sanitize() después de que la externa haya retornado.

Configuración Eliminada

OpciónDesdeNota
SAFE_FOR_JQUERY2.1.0No se requiere reemplazo.

Integración Continua

Actualmente usamos GitHub Actions en combinación con Playwright. Esto nos permite confirmar en cada commit que todo funciona en los navegadores modernos relevantes, y un flujo de trabajo separado programado y al fusionar vuelve a ejecutar la suite en instantáneas de motores más antiguos para que también se detecten fallos en navegadores obsoletos. Consulta los registros de compilación aquí: https://github.com/cure53/DOMPurify/actions

También puedes ejecutar pruebas locales ejecutando npm run test.

Todos los commits relevantes se firmarán con la clave 0x24BB6BF4 para mayor seguridad (desde el 8 de abril de 2016).

Desarrollo y contribución

Instalación (npm i)

Soportamos npm oficialmente. El flujo de trabajo de GitHub Actions está configurado para instalar dependencias usando npm. Cuando se usa una versión obsoleta de npm, no podemos garantizar completamente las versiones de las dependencias instaladas, lo que podría provocar problemas imprevistos.

Scripts

Usamos ESLint a través de xo como parte de nuestro flujo de trabajo previo al commit para ayudar a garantizar la consistencia del código. Además, usamos Prettier para el formato de fuentes y Markdown, y los activos de /dist se compilan mediante rollup.

Estos son nuestros scripts de npm:

  • npm run dev para compilar el bundle UMD sin minificar mientras se observan los cambios en las fuentes
  • npm run test para revisar el código de las fuentes, ejecutar pruebas a través de jsdom y ejecutar pruebas de navegador en Chromium mediante Playwright
    • npm run test:jsdom para ejecutar solo pruebas a través de jsdom
    • npm run test:happydom para ejecutar la suite a través de happy-dom (un entorno no soportado; se mantiene como comprobación de robustez, no como promesa de compatibilidad)
    • npm run test:browser para ejecutar solo pruebas a través de Playwright
    • npm run test:browser:legacy para ejecutar la suite en motores de navegador antiguos (apunta PW_MODULE a una instalación fijada antigua de Playwright; consulta .github/workflows/legacy-browsers.yml)
    • npm run test:ci para ejecutar el flujo de pruebas de CI para jsdom y Playwright
    • npm run test:fuzz para ejecutar un pequeño fuzzer que cubre sanitize() y CONFIG
  • npm run bench para ejecutar el micro-benchmark de jsdom sobre el dist/purify.cjs compilado (compila primero; --json y --compare a.json b.json admiten ejecuciones A/B entre ramas: los resultados son orientativos, confirma las afirmaciones orientadas al usuario en navegadores reales)
  • npm run coverage para compilar un bundle instrumentado, ejecutar la suite de jsdom y escribir un informe local HTML de cobertura de líneas/ramas en coverage/index.html (solo ámbito de jsdom, no se ejecuta en CI)
    • npm run build:cov para compilar solo el bundle de cobertura instrumentado
  • npm run lint para revisar el código de las fuentes usando ESLint a través de xo
  • npm run format para formatear fuentes JavaScript/TypeScript y Markdown con Prettier
    • npm run format:js para formatear solo fuentes JavaScript/TypeScript
    • npm run format:md para formatear solo archivos Markdown
  • npm run build para compilar declaraciones de tipos y bundles de distribución, y luego corregir y limpiar los tipos generados
    • npm run build:types para emitir solo archivos de declaración de TypeScript
    • npm run build:rollup para compilar todos los bundles de Rollup
    • npm run build:umd para compilar solo un bundle UMD sin minificar
    • npm run build:umd:min para compilar solo un bundle UMD minificado
    • npm run build:es para compilar solo el bundle de módulo ES
    • npm run build:cjs para compilar solo el bundle CommonJS
    • npm run build:fix-types para post-procesar los archivos de tipos generados
    • npm run build:cleanup para limpiar la salida temporal de tipos generados
  • npm run verify-typescript para ejecutar el script de verificación de TypeScript
  • npm run commit-amend-build para ejecutar el script auxiliar del mantenedor para enmendar la salida de compilación

Nota: todos los scripts se ejecutan mediante npm run <script>.

Hay más scripts de npm, pero principalmente están para integrarse con CI o están pensados para ser "privados", por ejemplo, para enmendar los archivos de distribución compilados con cada commit.

Lista de Correo de Seguridad

Mantenemos una lista de correo que notifica cada vez que se publica una versión crítica para la seguridad de DOMPurify. Esto significa que, si alguien encontró un bypass y lo corregimos con una versión (lo que siempre ocurre cuando se encuentra un bypass), se enviará un correo a esa lista. Esto suele ocurrir en minutos o unas pocas horas después de conocer el bypass. Puedes suscribirte a la lista aquí:

https://lists.ruhr-uni-bochum.de/mailman/listinfo/dompurify-security

Las versiones de funcionalidades no se anunciarán en esta lista.

¿Quién contribuyó?

¡Muchas personas han ayudado a que DOMPurify sea lo que es hoy, y merecen ser reconocidas!

gnyselcuk, leechristensen,offset, Bankde, lukewarlow, DEMON1A, fg0x0, kodareef5, DavidOliver, 1Jesper1, bencalif, trace37labs, eddieran, christos-eth, researchatfluidattacks, frevadiscor, Rotzbua, binhpv, MariusRumpf, prasadrajandran, Cybozu 💛💸, hata6502 💸, openclaw 💸, intra-mart-dh 💸, nelstrom ❤️, hash_kitten ❤️, kevin_mizu ❤️, icesfont ❤️, reduckted ❤️, dcramer 💸, JGraph 💸, baekilda 💸, Healthchecks 💸, Sentry 💸, jarrodldavis 💸, CynegeticIO, ssi02014 ❤️, GrantGryczan, Lowdefy, granlem, oreoshake, tdeekens ❤️, peernohell ❤️, is2ei, SoheilKhodayari, franktopel, NateScarlet, neilj, fhemberger, Joris-van-der-Wel, ydaniv, terjanq, filedescriptor, ConradIrwin, gibson042, choumx, 0xSobky, styfle, koto, tlau88, strugee, oparoz, mathiasbynens, edg2s, dnkolegov, dhardtke, wirehead, thorn0, styu, mozfreddyb ❤️, mikesamuel, jorangreef, jimmyhchan, jameydeorio, jameskraus, hyderali, hansottowirtz, hackvertor, freddyb, flavorjones, djfarrelly, devd, camerondunford, buu700, buildog, alabiaga, Vector919, Robbert, GreLI, FuzzySockets, ArtemBernatskyy, @garethheyes, @shafigullin, @mmrupp, @irsdl,ShikariSenpai, ansjdnakjdnajkd, @asutherland, @mathias, @cgvwzq, @robbertatwork, @giutro, @CmdEngineer_, @avr4mit, davecardwell, Develop-KIM, asamuzaK, fishjojo1 ❤️, Rikuxx0, donmccurdy, hhk-png, elrion018, michalnieruchalski-tiugo, reey, KanhaKanhaiya, odaysec, Akokonunes, alirezarouhbakhsh, Jaybhade y especialmente @securitymb ❤️ y @masatokinugawa ❤️

Categorías