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 +3 -3
- package/dist/purify.cjs.js +5 -59
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.mjs +5 -59
- package/dist/purify.es.mjs.map +1 -1
- package/dist/purify.js +5 -59
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +2 -2
- package/dist/purify.min.js.map +1 -1
- package/package.json +1 -1
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.
|
|
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.
|
|
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
|
|
48
|
+
import DOMPurify from 'dompurify';
|
|
49
49
|
|
|
50
50
|
const clean = DOMPurify.sanitize('<b>hello there</b>');
|
|
51
51
|
```
|
package/dist/purify.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @license DOMPurify 3.1.
|
|
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.
|
|
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
|
|
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
|
|