dompurify 2.3.2 → 2.3.6
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 +73 -31
- package/dist/purify.cjs.js +102 -37
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +102 -37
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +102 -37
- 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 +10 -15
package/dist/purify.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @license DOMPurify 2.3.
|
|
1
|
+
/*! @license DOMPurify 2.3.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.6/LICENSE */
|
|
2
2
|
|
|
3
3
|
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
|
4
4
|
|
|
@@ -150,13 +150,13 @@ var html = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside'
|
|
|
150
150
|
// SVG
|
|
151
151
|
var svg = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
|
|
152
152
|
|
|
153
|
-
var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
|
|
153
|
+
var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
|
|
154
154
|
|
|
155
155
|
// List of SVG elements that are disallowed by default.
|
|
156
156
|
// We still need to know them so that we can do namespace
|
|
157
157
|
// checks properly in case one wants to add them to
|
|
158
158
|
// allow-list.
|
|
159
|
-
var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', '
|
|
159
|
+
var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);
|
|
160
160
|
|
|
161
161
|
var mathMl = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);
|
|
162
162
|
|
|
@@ -166,9 +166,9 @@ var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv
|
|
|
166
166
|
|
|
167
167
|
var text = freeze(['#text']);
|
|
168
168
|
|
|
169
|
-
var html$1 = 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', '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']);
|
|
169
|
+
var html$1 = 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']);
|
|
170
170
|
|
|
171
|
-
var svg$1 = 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', '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']);
|
|
171
|
+
var svg$1 = 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']);
|
|
172
172
|
|
|
173
173
|
var mathMl$1 = 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']);
|
|
174
174
|
|
|
@@ -184,6 +184,7 @@ var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-
|
|
|
184
184
|
var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
|
|
185
185
|
var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
|
|
186
186
|
);
|
|
187
|
+
var DOCTYPE_NAME = seal(/^html$/i);
|
|
187
188
|
|
|
188
189
|
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
189
190
|
|
|
@@ -243,7 +244,7 @@ function createDOMPurify() {
|
|
|
243
244
|
* Version label, exposed for easier checks
|
|
244
245
|
* if DOMPurify is up to date or not
|
|
245
246
|
*/
|
|
246
|
-
DOMPurify.version = '2.3.
|
|
247
|
+
DOMPurify.version = '2.3.6';
|
|
247
248
|
|
|
248
249
|
/**
|
|
249
250
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -269,8 +270,7 @@ function createDOMPurify() {
|
|
|
269
270
|
NodeFilter = window.NodeFilter,
|
|
270
271
|
_window$NamedNodeMap = window.NamedNodeMap,
|
|
271
272
|
NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
|
|
272
|
-
|
|
273
|
-
Comment = window.Comment,
|
|
273
|
+
HTMLFormElement = window.HTMLFormElement,
|
|
274
274
|
DOMParser = window.DOMParser,
|
|
275
275
|
trustedTypes = window.trustedTypes;
|
|
276
276
|
|
|
@@ -296,7 +296,7 @@ function createDOMPurify() {
|
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
|
|
299
|
-
var emptyHTML = trustedTypesPolicy
|
|
299
|
+
var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
|
|
300
300
|
|
|
301
301
|
var _document = document,
|
|
302
302
|
implementation = _document.implementation,
|
|
@@ -340,6 +340,33 @@ function createDOMPurify() {
|
|
|
340
340
|
var ALLOWED_ATTR = null;
|
|
341
341
|
var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray$1(html$1), _toConsumableArray$1(svg$1), _toConsumableArray$1(mathMl$1), _toConsumableArray$1(xml)));
|
|
342
342
|
|
|
343
|
+
/*
|
|
344
|
+
* Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.
|
|
345
|
+
* @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
|
|
346
|
+
* @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)
|
|
347
|
+
* @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
|
|
348
|
+
*/
|
|
349
|
+
var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
|
|
350
|
+
tagNameCheck: {
|
|
351
|
+
writable: true,
|
|
352
|
+
configurable: false,
|
|
353
|
+
enumerable: true,
|
|
354
|
+
value: null
|
|
355
|
+
},
|
|
356
|
+
attributeNameCheck: {
|
|
357
|
+
writable: true,
|
|
358
|
+
configurable: false,
|
|
359
|
+
enumerable: true,
|
|
360
|
+
value: null
|
|
361
|
+
},
|
|
362
|
+
allowCustomizedBuiltInElements: {
|
|
363
|
+
writable: true,
|
|
364
|
+
configurable: false,
|
|
365
|
+
enumerable: true,
|
|
366
|
+
value: false
|
|
367
|
+
}
|
|
368
|
+
}));
|
|
369
|
+
|
|
343
370
|
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
|
|
344
371
|
var FORBID_TAGS = null;
|
|
345
372
|
|
|
@@ -380,17 +407,6 @@ function createDOMPurify() {
|
|
|
380
407
|
* string (or a TrustedHTML object if Trusted Types are supported) */
|
|
381
408
|
var RETURN_DOM_FRAGMENT = false;
|
|
382
409
|
|
|
383
|
-
/* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
|
|
384
|
-
* `Node` is imported into the current `Document`. If this flag is not enabled the
|
|
385
|
-
* `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
|
|
386
|
-
* DOMPurify.
|
|
387
|
-
*
|
|
388
|
-
* This defaults to `true` starting DOMPurify 2.2.0. Note that setting it to `false`
|
|
389
|
-
* might cause XSS from attacks hidden in closed shadowroots in case the browser
|
|
390
|
-
* supports Declarative Shadow: DOM https://web.dev/declarative-shadow-dom/
|
|
391
|
-
*/
|
|
392
|
-
var RETURN_DOM_IMPORT = true;
|
|
393
|
-
|
|
394
410
|
/* Try to return a Trusted Type object instead of a string, return a string in
|
|
395
411
|
* case Trusted Types are not supported */
|
|
396
412
|
var RETURN_TRUSTED_TYPE = false;
|
|
@@ -441,6 +457,10 @@ function createDOMPurify() {
|
|
|
441
457
|
|
|
442
458
|
var formElement = document.createElement('form');
|
|
443
459
|
|
|
460
|
+
var isRegexOrFunction = function isRegexOrFunction(testValue) {
|
|
461
|
+
return testValue instanceof RegExp || testValue instanceof Function;
|
|
462
|
+
};
|
|
463
|
+
|
|
444
464
|
/**
|
|
445
465
|
* _parseConfig
|
|
446
466
|
*
|
|
@@ -476,7 +496,6 @@ function createDOMPurify() {
|
|
|
476
496
|
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
|
|
477
497
|
RETURN_DOM = cfg.RETURN_DOM || false; // Default false
|
|
478
498
|
RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
|
|
479
|
-
RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT !== false; // Default true
|
|
480
499
|
RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
|
|
481
500
|
FORCE_BODY = cfg.FORCE_BODY || false; // Default false
|
|
482
501
|
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
|
@@ -484,7 +503,22 @@ function createDOMPurify() {
|
|
|
484
503
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
485
504
|
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
486
505
|
NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
|
|
487
|
-
|
|
506
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
|
|
507
|
+
CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
|
|
511
|
+
CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
|
|
515
|
+
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
PARSER_MEDIA_TYPE =
|
|
519
|
+
// eslint-disable-next-line unicorn/prefer-includes
|
|
520
|
+
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
|
|
521
|
+
|
|
488
522
|
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
489
523
|
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
|
|
490
524
|
return x;
|
|
@@ -805,7 +839,9 @@ function createDOMPurify() {
|
|
|
805
839
|
* @return {Iterator} iterator instance
|
|
806
840
|
*/
|
|
807
841
|
var _createIterator = function _createIterator(root) {
|
|
808
|
-
return createNodeIterator.call(root.ownerDocument || root, root,
|
|
842
|
+
return createNodeIterator.call(root.ownerDocument || root, root,
|
|
843
|
+
// eslint-disable-next-line no-bitwise
|
|
844
|
+
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
|
|
809
845
|
};
|
|
810
846
|
|
|
811
847
|
/**
|
|
@@ -815,15 +851,7 @@ function createDOMPurify() {
|
|
|
815
851
|
* @return {Boolean} true if clobbered, false if safe
|
|
816
852
|
*/
|
|
817
853
|
var _isClobbered = function _isClobbered(elm) {
|
|
818
|
-
|
|
819
|
-
return false;
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
if (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') {
|
|
823
|
-
return true;
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
return false;
|
|
854
|
+
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');
|
|
827
855
|
};
|
|
828
856
|
|
|
829
857
|
/**
|
|
@@ -905,6 +933,12 @@ function createDOMPurify() {
|
|
|
905
933
|
|
|
906
934
|
/* Remove element if anything forbids its presence */
|
|
907
935
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
936
|
+
/* Check if we have a custom element to handle */
|
|
937
|
+
if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
|
|
938
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
|
|
939
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
|
|
940
|
+
}
|
|
941
|
+
|
|
908
942
|
/* Keep content except for bad-listed elements */
|
|
909
943
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
910
944
|
var parentNode = getParentNode(currentNode) || currentNode.parentNode;
|
|
@@ -972,8 +1006,16 @@ function createDOMPurify() {
|
|
|
972
1006
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
973
1007
|
We don't need to check the value; it's always URI safe. */
|
|
974
1008
|
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
975
|
-
|
|
976
|
-
|
|
1009
|
+
if (
|
|
1010
|
+
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
1011
|
+
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1012
|
+
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
|
|
1013
|
+
_basicCustomElementTest(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||
|
|
1014
|
+
// Alternative, second condition checks if it's an `is`-attribute, AND
|
|
1015
|
+
// the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1016
|
+
lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {
|
|
1017
|
+
return false;
|
|
1018
|
+
}
|
|
977
1019
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
978
1020
|
} else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) ; else if (!value) ; else {
|
|
979
1021
|
return false;
|
|
@@ -982,6 +1024,16 @@ function createDOMPurify() {
|
|
|
982
1024
|
return true;
|
|
983
1025
|
};
|
|
984
1026
|
|
|
1027
|
+
/**
|
|
1028
|
+
* _basicCustomElementCheck
|
|
1029
|
+
* checks if at least one dash is included in tagName, and it's not the first char
|
|
1030
|
+
* for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
|
|
1031
|
+
* @param {string} tagName name of the tag of the node to sanitize
|
|
1032
|
+
*/
|
|
1033
|
+
var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
|
|
1034
|
+
return tagName.indexOf('-') > 0;
|
|
1035
|
+
};
|
|
1036
|
+
|
|
985
1037
|
/**
|
|
986
1038
|
* _sanitizeAttributes
|
|
987
1039
|
*
|
|
@@ -1178,7 +1230,15 @@ function createDOMPurify() {
|
|
|
1178
1230
|
IN_PLACE = false;
|
|
1179
1231
|
}
|
|
1180
1232
|
|
|
1181
|
-
if (IN_PLACE)
|
|
1233
|
+
if (IN_PLACE) {
|
|
1234
|
+
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
1235
|
+
if (dirty.nodeName) {
|
|
1236
|
+
var tagName = transformCaseFunc(dirty.nodeName);
|
|
1237
|
+
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
1238
|
+
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
} else if (dirty instanceof Node) {
|
|
1182
1242
|
/* If dirty is a DOM element, append to an empty document to avoid
|
|
1183
1243
|
elements being stripped by the parser */
|
|
1184
1244
|
body = _initDocument('<!---->');
|
|
@@ -1205,7 +1265,7 @@ function createDOMPurify() {
|
|
|
1205
1265
|
|
|
1206
1266
|
/* Check we have a DOM node from the data */
|
|
1207
1267
|
if (!body) {
|
|
1208
|
-
return RETURN_DOM ? null : emptyHTML;
|
|
1268
|
+
return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
|
|
1209
1269
|
}
|
|
1210
1270
|
}
|
|
1211
1271
|
|
|
@@ -1260,7 +1320,7 @@ function createDOMPurify() {
|
|
|
1260
1320
|
returnNode = body;
|
|
1261
1321
|
}
|
|
1262
1322
|
|
|
1263
|
-
if (
|
|
1323
|
+
if (ALLOWED_ATTR.shadowroot) {
|
|
1264
1324
|
/*
|
|
1265
1325
|
AdoptNode() is not used because internal state is not reset
|
|
1266
1326
|
(e.g. the past names map of a HTMLFormElement), this is safe
|
|
@@ -1276,6 +1336,11 @@ function createDOMPurify() {
|
|
|
1276
1336
|
|
|
1277
1337
|
var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
|
1278
1338
|
|
|
1339
|
+
/* Serialize doctype if allowed */
|
|
1340
|
+
if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
|
|
1341
|
+
serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1279
1344
|
/* Sanitize final string template-safe */
|
|
1280
1345
|
if (SAFE_FOR_TEMPLATES) {
|
|
1281
1346
|
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
|