dompurify 2.3.1 → 2.3.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 +70 -31
- package/dist/purify.cjs.js +114 -41
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +114 -41
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +114 -41
- 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 +4 -8
package/dist/purify.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @license DOMPurify 2.3.
|
|
1
|
+
/*! @license DOMPurify 2.3.5 | (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.5/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
|
|
|
@@ -243,7 +243,7 @@ function createDOMPurify() {
|
|
|
243
243
|
* Version label, exposed for easier checks
|
|
244
244
|
* if DOMPurify is up to date or not
|
|
245
245
|
*/
|
|
246
|
-
DOMPurify.version = '2.3.
|
|
246
|
+
DOMPurify.version = '2.3.5';
|
|
247
247
|
|
|
248
248
|
/**
|
|
249
249
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -269,8 +269,7 @@ function createDOMPurify() {
|
|
|
269
269
|
NodeFilter = window.NodeFilter,
|
|
270
270
|
_window$NamedNodeMap = window.NamedNodeMap,
|
|
271
271
|
NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
|
|
272
|
-
|
|
273
|
-
Comment = window.Comment,
|
|
272
|
+
HTMLFormElement = window.HTMLFormElement,
|
|
274
273
|
DOMParser = window.DOMParser,
|
|
275
274
|
trustedTypes = window.trustedTypes;
|
|
276
275
|
|
|
@@ -296,7 +295,7 @@ function createDOMPurify() {
|
|
|
296
295
|
}
|
|
297
296
|
|
|
298
297
|
var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
|
|
299
|
-
var emptyHTML = trustedTypesPolicy
|
|
298
|
+
var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
|
|
300
299
|
|
|
301
300
|
var _document = document,
|
|
302
301
|
implementation = _document.implementation,
|
|
@@ -340,6 +339,33 @@ function createDOMPurify() {
|
|
|
340
339
|
var ALLOWED_ATTR = null;
|
|
341
340
|
var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray$1(html$1), _toConsumableArray$1(svg$1), _toConsumableArray$1(mathMl$1), _toConsumableArray$1(xml)));
|
|
342
341
|
|
|
342
|
+
/*
|
|
343
|
+
* Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.
|
|
344
|
+
* @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
|
|
345
|
+
* @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)
|
|
346
|
+
* @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
|
|
347
|
+
*/
|
|
348
|
+
var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
|
|
349
|
+
tagNameCheck: {
|
|
350
|
+
writable: true,
|
|
351
|
+
configurable: false,
|
|
352
|
+
enumerable: true,
|
|
353
|
+
value: null
|
|
354
|
+
},
|
|
355
|
+
attributeNameCheck: {
|
|
356
|
+
writable: true,
|
|
357
|
+
configurable: false,
|
|
358
|
+
enumerable: true,
|
|
359
|
+
value: null
|
|
360
|
+
},
|
|
361
|
+
allowCustomizedBuiltInElements: {
|
|
362
|
+
writable: true,
|
|
363
|
+
configurable: false,
|
|
364
|
+
enumerable: true,
|
|
365
|
+
value: false
|
|
366
|
+
}
|
|
367
|
+
}));
|
|
368
|
+
|
|
343
369
|
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
|
|
344
370
|
var FORBID_TAGS = null;
|
|
345
371
|
|
|
@@ -380,17 +406,6 @@ function createDOMPurify() {
|
|
|
380
406
|
* string (or a TrustedHTML object if Trusted Types are supported) */
|
|
381
407
|
var RETURN_DOM_FRAGMENT = false;
|
|
382
408
|
|
|
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
409
|
/* Try to return a Trusted Type object instead of a string, return a string in
|
|
395
410
|
* case Trusted Types are not supported */
|
|
396
411
|
var RETURN_TRUSTED_TYPE = false;
|
|
@@ -427,6 +442,12 @@ function createDOMPurify() {
|
|
|
427
442
|
var NAMESPACE = HTML_NAMESPACE;
|
|
428
443
|
var IS_EMPTY_INPUT = false;
|
|
429
444
|
|
|
445
|
+
/* Parsing of strict XHTML documents */
|
|
446
|
+
var PARSER_MEDIA_TYPE = void 0;
|
|
447
|
+
var SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
|
|
448
|
+
var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
|
|
449
|
+
var transformCaseFunc = void 0;
|
|
450
|
+
|
|
430
451
|
/* Keep a reference to config to pass to hooks */
|
|
431
452
|
var CONFIG = null;
|
|
432
453
|
|
|
@@ -435,6 +456,10 @@ function createDOMPurify() {
|
|
|
435
456
|
|
|
436
457
|
var formElement = document.createElement('form');
|
|
437
458
|
|
|
459
|
+
var isRegexOrFunction = function isRegexOrFunction(testValue) {
|
|
460
|
+
return testValue instanceof RegExp || testValue instanceof Function;
|
|
461
|
+
};
|
|
462
|
+
|
|
438
463
|
/**
|
|
439
464
|
* _parseConfig
|
|
440
465
|
*
|
|
@@ -470,7 +495,6 @@ function createDOMPurify() {
|
|
|
470
495
|
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
|
|
471
496
|
RETURN_DOM = cfg.RETURN_DOM || false; // Default false
|
|
472
497
|
RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
|
|
473
|
-
RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT !== false; // Default true
|
|
474
498
|
RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
|
|
475
499
|
FORCE_BODY = cfg.FORCE_BODY || false; // Default false
|
|
476
500
|
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
|
@@ -478,6 +502,27 @@ function createDOMPurify() {
|
|
|
478
502
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
479
503
|
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
480
504
|
NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
|
|
505
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
|
|
506
|
+
CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
|
|
510
|
+
CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
|
|
514
|
+
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
PARSER_MEDIA_TYPE =
|
|
518
|
+
// eslint-disable-next-line unicorn/prefer-includes
|
|
519
|
+
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
|
|
520
|
+
|
|
521
|
+
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
522
|
+
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
|
|
523
|
+
return x;
|
|
524
|
+
} : stringToLowerCase;
|
|
525
|
+
|
|
481
526
|
if (SAFE_FOR_TEMPLATES) {
|
|
482
527
|
ALLOW_DATA_ATTR = false;
|
|
483
528
|
}
|
|
@@ -746,6 +791,11 @@ function createDOMPurify() {
|
|
|
746
791
|
leadingWhitespace = matches && matches[0];
|
|
747
792
|
}
|
|
748
793
|
|
|
794
|
+
if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') {
|
|
795
|
+
// Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
|
|
796
|
+
dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
|
|
797
|
+
}
|
|
798
|
+
|
|
749
799
|
var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
750
800
|
/*
|
|
751
801
|
* Use the DOMParser API by default, fallback later if needs be
|
|
@@ -753,7 +803,7 @@ function createDOMPurify() {
|
|
|
753
803
|
*/
|
|
754
804
|
if (NAMESPACE === HTML_NAMESPACE) {
|
|
755
805
|
try {
|
|
756
|
-
doc = new DOMParser().parseFromString(dirtyPayload,
|
|
806
|
+
doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
|
|
757
807
|
} catch (_) {}
|
|
758
808
|
}
|
|
759
809
|
|
|
@@ -798,15 +848,7 @@ function createDOMPurify() {
|
|
|
798
848
|
* @return {Boolean} true if clobbered, false if safe
|
|
799
849
|
*/
|
|
800
850
|
var _isClobbered = function _isClobbered(elm) {
|
|
801
|
-
|
|
802
|
-
return false;
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
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') {
|
|
806
|
-
return true;
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
return false;
|
|
851
|
+
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');
|
|
810
852
|
};
|
|
811
853
|
|
|
812
854
|
/**
|
|
@@ -866,7 +908,7 @@ function createDOMPurify() {
|
|
|
866
908
|
}
|
|
867
909
|
|
|
868
910
|
/* Now let's check the element's type and name */
|
|
869
|
-
var tagName =
|
|
911
|
+
var tagName = transformCaseFunc(currentNode.nodeName);
|
|
870
912
|
|
|
871
913
|
/* Execute a hook if present */
|
|
872
914
|
_executeHook('uponSanitizeElement', currentNode, {
|
|
@@ -902,6 +944,11 @@ function createDOMPurify() {
|
|
|
902
944
|
}
|
|
903
945
|
}
|
|
904
946
|
|
|
947
|
+
if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
|
|
948
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
|
|
949
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
|
|
950
|
+
}
|
|
951
|
+
|
|
905
952
|
_forceRemove(currentNode);
|
|
906
953
|
return true;
|
|
907
954
|
}
|
|
@@ -955,8 +1002,16 @@ function createDOMPurify() {
|
|
|
955
1002
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
956
1003
|
We don't need to check the value; it's always URI safe. */
|
|
957
1004
|
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]) {
|
|
958
|
-
|
|
959
|
-
|
|
1005
|
+
if (
|
|
1006
|
+
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
1007
|
+
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1008
|
+
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
|
|
1009
|
+
_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)) ||
|
|
1010
|
+
// Alternative, second condition checks if it's an `is`-attribute, AND
|
|
1011
|
+
// the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1012
|
+
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 {
|
|
1013
|
+
return false;
|
|
1014
|
+
}
|
|
960
1015
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
961
1016
|
} 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 {
|
|
962
1017
|
return false;
|
|
@@ -965,6 +1020,16 @@ function createDOMPurify() {
|
|
|
965
1020
|
return true;
|
|
966
1021
|
};
|
|
967
1022
|
|
|
1023
|
+
/**
|
|
1024
|
+
* _basicCustomElementCheck
|
|
1025
|
+
* checks if at least one dash is included in tagName, and it's not the first char
|
|
1026
|
+
* for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
|
|
1027
|
+
* @param {string} tagName name of the tag of the node to sanitize
|
|
1028
|
+
*/
|
|
1029
|
+
var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
|
|
1030
|
+
return tagName.indexOf('-') > 0;
|
|
1031
|
+
};
|
|
1032
|
+
|
|
968
1033
|
/**
|
|
969
1034
|
* _sanitizeAttributes
|
|
970
1035
|
*
|
|
@@ -1007,7 +1072,7 @@ function createDOMPurify() {
|
|
|
1007
1072
|
namespaceURI = _attr.namespaceURI;
|
|
1008
1073
|
|
|
1009
1074
|
value = stringTrim(attr.value);
|
|
1010
|
-
lcName =
|
|
1075
|
+
lcName = transformCaseFunc(name);
|
|
1011
1076
|
|
|
1012
1077
|
/* Execute a hook if present */
|
|
1013
1078
|
hookEvent.attrName = lcName;
|
|
@@ -1042,7 +1107,7 @@ function createDOMPurify() {
|
|
|
1042
1107
|
}
|
|
1043
1108
|
|
|
1044
1109
|
/* Is `value` valid for this attribute? */
|
|
1045
|
-
var lcTag = currentNode.nodeName
|
|
1110
|
+
var lcTag = transformCaseFunc(currentNode.nodeName);
|
|
1046
1111
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
1047
1112
|
continue;
|
|
1048
1113
|
}
|
|
@@ -1161,7 +1226,15 @@ function createDOMPurify() {
|
|
|
1161
1226
|
IN_PLACE = false;
|
|
1162
1227
|
}
|
|
1163
1228
|
|
|
1164
|
-
if (IN_PLACE)
|
|
1229
|
+
if (IN_PLACE) {
|
|
1230
|
+
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
1231
|
+
if (dirty.nodeName) {
|
|
1232
|
+
var tagName = transformCaseFunc(dirty.nodeName);
|
|
1233
|
+
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
1234
|
+
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
} else if (dirty instanceof Node) {
|
|
1165
1238
|
/* If dirty is a DOM element, append to an empty document to avoid
|
|
1166
1239
|
elements being stripped by the parser */
|
|
1167
1240
|
body = _initDocument('<!---->');
|
|
@@ -1188,7 +1261,7 @@ function createDOMPurify() {
|
|
|
1188
1261
|
|
|
1189
1262
|
/* Check we have a DOM node from the data */
|
|
1190
1263
|
if (!body) {
|
|
1191
|
-
return RETURN_DOM ? null : emptyHTML;
|
|
1264
|
+
return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
|
|
1192
1265
|
}
|
|
1193
1266
|
}
|
|
1194
1267
|
|
|
@@ -1243,7 +1316,7 @@ function createDOMPurify() {
|
|
|
1243
1316
|
returnNode = body;
|
|
1244
1317
|
}
|
|
1245
1318
|
|
|
1246
|
-
if (
|
|
1319
|
+
if (ALLOWED_ATTR.shadowroot) {
|
|
1247
1320
|
/*
|
|
1248
1321
|
AdoptNode() is not used because internal state is not reset
|
|
1249
1322
|
(e.g. the past names map of a HTMLFormElement), this is safe
|
|
@@ -1305,8 +1378,8 @@ function createDOMPurify() {
|
|
|
1305
1378
|
_parseConfig({});
|
|
1306
1379
|
}
|
|
1307
1380
|
|
|
1308
|
-
var lcTag =
|
|
1309
|
-
var lcName =
|
|
1381
|
+
var lcTag = transformCaseFunc(tag);
|
|
1382
|
+
var lcName = transformCaseFunc(attr);
|
|
1310
1383
|
return _isValidAttribute(lcTag, lcName, value);
|
|
1311
1384
|
};
|
|
1312
1385
|
|