dompurify 3.1.3 → 3.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,11 +6,11 @@
6
6
 
7
7
  DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG.
8
8
 
9
- It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version **v3.1.3**.
9
+ It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version **v3.1.5**.
10
10
 
11
11
  DOMPurify is written in JavaScript and works in all modern browsers (Safari (10+), Opera (15+), Edge, Firefox and Chrome - as well as almost anything else using Blink, Gecko or WebKit). It doesn't break on MSIE or other legacy browsers. It simply does nothing.
12
12
 
13
- **Note that [DOMPurify v2.5.3](https://github.com/cure53/DOMPurify/releases/tag/2.5.3) is the latest version supporting MSIE. For important security updates compatible with MSIE, please use the [2.x branch](https://github.com/cure53/DOMPurify/tree/2.x).**
13
+ **Note that [DOMPurify v2.5.5](https://github.com/cure53/DOMPurify/releases/tag/2.5.5) is the latest version supporting MSIE. For important security updates compatible with MSIE, please use the [2.x branch](https://github.com/cure53/DOMPurify/tree/2.x).**
14
14
 
15
15
  Our automated tests cover [19 different browsers](https://github.com/cure53/DOMPurify/blob/main/test/karma.custom-launchers.config.js#L5) right now, more to come. We also cover Node.js v16.x, v17.x, v18.x and v19.x, running DOMPurify on [jsdom](https://github.com/jsdom/jsdom). Older Node versions are known to work as well, but hey... no guarantees.
16
16
 
@@ -45,7 +45,7 @@ const clean = DOMPurify.sanitize(dirty);
45
45
  Or maybe this, if you love working with Angular or alike:
46
46
 
47
47
  ```js
48
- import * as DOMPurify from 'dompurify';
48
+ import DOMPurify from 'dompurify';
49
49
 
50
50
  const clean = DOMPurify.sanitize('<b>hello there</b>');
51
51
  ```
@@ -1,4 +1,4 @@
1
- /*! @license DOMPurify 3.1.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.1.3/LICENSE */
1
+ /*! @license DOMPurify 3.1.5 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.1.5/LICENSE */
2
2
 
3
3
  'use strict';
4
4
 
@@ -50,7 +50,6 @@ const stringTrim = unapply(String.prototype.trim);
50
50
  const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
51
51
  const regExpTest = unapply(RegExp.prototype.test);
52
52
  const typeErrorCreate = unconstruct(TypeError);
53
- const numberIsNaN = unapply(Number.isNaN);
54
53
 
55
54
  /**
56
55
  * Creates a new function that calls the given function with a specified thisArg and arguments.
@@ -199,7 +198,7 @@ const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mgly
199
198
  const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
200
199
  const text = freeze(['#text']);
201
200
 
202
- const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);
201
+ const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);
203
202
  const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
204
203
  const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
205
204
  const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
@@ -303,7 +302,7 @@ function createDOMPurify() {
303
302
  * Version label, exposed for easier checks
304
303
  * if DOMPurify is up to date or not
305
304
  */
306
- DOMPurify.version = '3.1.3';
305
+ DOMPurify.version = '3.1.5';
307
306
 
308
307
  /**
309
308
  * Array of elements that DOMPurify removed during sanitation.
@@ -536,9 +535,6 @@ function createDOMPurify() {
536
535
  /* Keep a reference to config to pass to hooks */
537
536
  let CONFIG = null;
538
537
 
539
- /* Specify the maximum element nesting depth to prevent mXSS */
540
- const MAX_NESTING_DEPTH = 255;
541
-
542
538
  /* Ideally, do not touch anything below this line */
543
539
  /* ______________________________________________ */
544
540
 
@@ -949,11 +945,7 @@ function createDOMPurify() {
949
945
  * @return {Boolean} true if clobbered, false if safe
950
946
  */
951
947
  const _isClobbered = function _isClobbered(elm) {
952
- return elm instanceof HTMLFormElement && (
953
- // eslint-disable-next-line unicorn/no-typeof-undefined
954
- typeof elm.__depth !== 'undefined' && typeof elm.__depth !== 'number' ||
955
- // eslint-disable-next-line unicorn/no-typeof-undefined
956
- typeof elm.__removalCount !== 'undefined' && typeof elm.__removalCount !== 'number' || typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');
948
+ return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');
957
949
  };
958
950
 
959
951
  /**
@@ -1104,7 +1096,7 @@ function createDOMPurify() {
1104
1096
  // eslint-disable-next-line complexity
1105
1097
  const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1106
1098
  /* Make sure attribute cannot clobber */
1107
- if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement || value === '__depth' || value === '__removalCount')) {
1099
+ if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1108
1100
  return false;
1109
1101
  }
1110
1102
 
@@ -1295,32 +1287,9 @@ function createDOMPurify() {
1295
1287
  if (_sanitizeElements(shadowNode)) {
1296
1288
  continue;
1297
1289
  }
1298
- const parentNode = getParentNode(shadowNode);
1299
-
1300
- /* Set the nesting depth of an element */
1301
- if (shadowNode.nodeType === NODE_TYPE.element) {
1302
- if (parentNode && parentNode.__depth) {
1303
- /*
1304
- We want the depth of the node in the original tree, which can
1305
- change when it's removed from its parent.
1306
- */
1307
- shadowNode.__depth = (shadowNode.__removalCount || 0) + parentNode.__depth + 1;
1308
- } else {
1309
- shadowNode.__depth = 1;
1310
- }
1311
- }
1312
-
1313
- /*
1314
- * Remove an element if nested too deeply to avoid mXSS
1315
- * or if the __depth might have been tampered with
1316
- */
1317
- if (shadowNode.__depth >= MAX_NESTING_DEPTH || shadowNode.__depth < 0 || numberIsNaN(shadowNode.__depth)) {
1318
- _forceRemove(shadowNode);
1319
- }
1320
1290
 
1321
1291
  /* Deep shadow DOM detected */
1322
1292
  if (shadowNode.content instanceof DocumentFragment) {
1323
- shadowNode.content.__depth = shadowNode.__depth;
1324
1293
  _sanitizeShadowDOM(shadowNode.content);
1325
1294
  }
1326
1295
 
@@ -1436,32 +1405,9 @@ function createDOMPurify() {
1436
1405
  if (_sanitizeElements(currentNode)) {
1437
1406
  continue;
1438
1407
  }
1439
- const parentNode = getParentNode(currentNode);
1440
-
1441
- /* Set the nesting depth of an element */
1442
- if (currentNode.nodeType === NODE_TYPE.element) {
1443
- if (parentNode && parentNode.__depth) {
1444
- /*
1445
- We want the depth of the node in the original tree, which can
1446
- change when it's removed from its parent.
1447
- */
1448
- currentNode.__depth = (currentNode.__removalCount || 0) + parentNode.__depth + 1;
1449
- } else {
1450
- currentNode.__depth = 1;
1451
- }
1452
- }
1453
-
1454
- /*
1455
- * Remove an element if nested too deeply to avoid mXSS
1456
- * or if the __depth might have been tampered with
1457
- */
1458
- if (currentNode.__depth >= MAX_NESTING_DEPTH || currentNode.__depth < 0 || numberIsNaN(currentNode.__depth)) {
1459
- _forceRemove(currentNode);
1460
- }
1461
1408
 
1462
1409
  /* Shadow DOM detected, sanitize it */
1463
1410
  if (currentNode.content instanceof DocumentFragment) {
1464
- currentNode.content.__depth = currentNode.__depth;
1465
1411
  _sanitizeShadowDOM(currentNode.content);
1466
1412
  }
1467
1413