dompurify 3.0.11 → 3.1.1
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/LICENSE +1 -1
- package/README.md +21 -6
- package/dist/purify.cjs.js +64 -5
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.mjs +64 -5
- package/dist/purify.es.mjs.map +1 -1
- package/dist/purify.js +64 -5
- 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/dist/purify.es.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @license DOMPurify 3.
|
|
1
|
+
/*! @license DOMPurify 3.1.1 | (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.1/LICENSE */
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
4
|
entries,
|
|
@@ -196,7 +196,7 @@ const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mgly
|
|
|
196
196
|
const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
197
197
|
const text = freeze(['#text']);
|
|
198
198
|
|
|
199
|
-
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', 'xmlns', 'slot']);
|
|
199
|
+
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']);
|
|
200
200
|
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']);
|
|
201
201
|
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']);
|
|
202
202
|
const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
@@ -282,7 +282,7 @@ function createDOMPurify() {
|
|
|
282
282
|
* Version label, exposed for easier checks
|
|
283
283
|
* if DOMPurify is up to date or not
|
|
284
284
|
*/
|
|
285
|
-
DOMPurify.version = '3.
|
|
285
|
+
DOMPurify.version = '3.1.1';
|
|
286
286
|
|
|
287
287
|
/**
|
|
288
288
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -424,6 +424,11 @@ function createDOMPurify() {
|
|
|
424
424
|
*/
|
|
425
425
|
let SAFE_FOR_TEMPLATES = false;
|
|
426
426
|
|
|
427
|
+
/* Output should be safe even for XML used within HTML and alike.
|
|
428
|
+
* This means, DOMPurify removes comments when containing risky content.
|
|
429
|
+
*/
|
|
430
|
+
let SAFE_FOR_XML = true;
|
|
431
|
+
|
|
427
432
|
/* Decide if document with <html>... should be returned */
|
|
428
433
|
let WHOLE_DOCUMENT = false;
|
|
429
434
|
|
|
@@ -510,6 +515,9 @@ function createDOMPurify() {
|
|
|
510
515
|
/* Keep a reference to config to pass to hooks */
|
|
511
516
|
let CONFIG = null;
|
|
512
517
|
|
|
518
|
+
/* Specify the maximum element nesting depth to prevent mXSS */
|
|
519
|
+
const MAX_NESTING_DEPTH = 255;
|
|
520
|
+
|
|
513
521
|
/* Ideally, do not touch anything below this line */
|
|
514
522
|
/* ______________________________________________ */
|
|
515
523
|
|
|
@@ -571,6 +579,7 @@ function createDOMPurify() {
|
|
|
571
579
|
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
|
|
572
580
|
ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true
|
|
573
581
|
SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
|
|
582
|
+
SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true
|
|
574
583
|
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
|
|
575
584
|
RETURN_DOM = cfg.RETURN_DOM || false; // Default false
|
|
576
585
|
RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
|
|
@@ -919,7 +928,11 @@ function createDOMPurify() {
|
|
|
919
928
|
* @return {Boolean} true if clobbered, false if safe
|
|
920
929
|
*/
|
|
921
930
|
const _isClobbered = function _isClobbered(elm) {
|
|
922
|
-
return elm instanceof HTMLFormElement && (
|
|
931
|
+
return elm instanceof HTMLFormElement && (
|
|
932
|
+
// eslint-disable-next-line unicorn/no-typeof-undefined
|
|
933
|
+
typeof elm.__depth !== 'undefined' && typeof elm.__depth !== 'number' ||
|
|
934
|
+
// eslint-disable-next-line unicorn/no-typeof-undefined
|
|
935
|
+
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');
|
|
923
936
|
};
|
|
924
937
|
|
|
925
938
|
/**
|
|
@@ -992,6 +1005,12 @@ function createDOMPurify() {
|
|
|
992
1005
|
return true;
|
|
993
1006
|
}
|
|
994
1007
|
|
|
1008
|
+
/* Remove any kind of possibly harmful comments */
|
|
1009
|
+
if (SAFE_FOR_XML && currentNode.nodeType === 8 && regExpTest(/<[/\w]/g, currentNode.data)) {
|
|
1010
|
+
_forceRemove(currentNode);
|
|
1011
|
+
return true;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
995
1014
|
/* Remove element if anything forbids its presence */
|
|
996
1015
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
997
1016
|
/* Check if we have a custom element to handle */
|
|
@@ -1011,7 +1030,9 @@ function createDOMPurify() {
|
|
|
1011
1030
|
if (childNodes && parentNode) {
|
|
1012
1031
|
const childCount = childNodes.length;
|
|
1013
1032
|
for (let i = childCount - 1; i >= 0; --i) {
|
|
1014
|
-
|
|
1033
|
+
const childClone = cloneNode(childNodes[i], true);
|
|
1034
|
+
childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
|
|
1035
|
+
parentNode.insertBefore(childClone, getNextSibling(currentNode));
|
|
1015
1036
|
}
|
|
1016
1037
|
}
|
|
1017
1038
|
}
|
|
@@ -1244,8 +1265,27 @@ function createDOMPurify() {
|
|
|
1244
1265
|
continue;
|
|
1245
1266
|
}
|
|
1246
1267
|
|
|
1268
|
+
/* Set the nesting depth of an element */
|
|
1269
|
+
if (shadowNode.nodeType === 1) {
|
|
1270
|
+
if (shadowNode.parentNode && shadowNode.parentNode.__depth) {
|
|
1271
|
+
/*
|
|
1272
|
+
We want the depth of the node in the original tree, which can
|
|
1273
|
+
change when it's removed from its parent.
|
|
1274
|
+
*/
|
|
1275
|
+
shadowNode.__depth = (shadowNode.__removalCount || 0) + shadowNode.parentNode.__depth + 1;
|
|
1276
|
+
} else {
|
|
1277
|
+
shadowNode.__depth = 1;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/* Remove an element if nested too deeply to avoid mXSS */
|
|
1282
|
+
if (shadowNode.__depth >= MAX_NESTING_DEPTH) {
|
|
1283
|
+
_forceRemove(shadowNode);
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1247
1286
|
/* Deep shadow DOM detected */
|
|
1248
1287
|
if (shadowNode.content instanceof DocumentFragment) {
|
|
1288
|
+
shadowNode.content.__depth = shadowNode.__depth;
|
|
1249
1289
|
_sanitizeShadowDOM(shadowNode.content);
|
|
1250
1290
|
}
|
|
1251
1291
|
|
|
@@ -1362,8 +1402,27 @@ function createDOMPurify() {
|
|
|
1362
1402
|
continue;
|
|
1363
1403
|
}
|
|
1364
1404
|
|
|
1405
|
+
/* Set the nesting depth of an element */
|
|
1406
|
+
if (currentNode.nodeType === 1) {
|
|
1407
|
+
if (currentNode.parentNode && currentNode.parentNode.__depth) {
|
|
1408
|
+
/*
|
|
1409
|
+
We want the depth of the node in the original tree, which can
|
|
1410
|
+
change when it's removed from its parent.
|
|
1411
|
+
*/
|
|
1412
|
+
currentNode.__depth = (currentNode.__removalCount || 0) + currentNode.parentNode.__depth + 1;
|
|
1413
|
+
} else {
|
|
1414
|
+
currentNode.__depth = 1;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
/* Remove an element if nested too deeply to avoid mXSS */
|
|
1419
|
+
if (currentNode.__depth >= MAX_NESTING_DEPTH) {
|
|
1420
|
+
_forceRemove(currentNode);
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1365
1423
|
/* Shadow DOM detected, sanitize it */
|
|
1366
1424
|
if (currentNode.content instanceof DocumentFragment) {
|
|
1425
|
+
currentNode.content.__depth = currentNode.__depth;
|
|
1367
1426
|
_sanitizeShadowDOM(currentNode.content);
|
|
1368
1427
|
}
|
|
1369
1428
|
|