dompurify 2.3.0 → 2.3.4
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 +55 -16
- package/dist/purify.cjs.js +120 -39
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +120 -39
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +120 -39
- 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.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @license DOMPurify 2.3.
|
|
1
|
+
/*! @license DOMPurify 2.3.4 | (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.4/LICENSE */
|
|
2
2
|
|
|
3
3
|
(function (global, factory) {
|
|
4
4
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
@@ -156,13 +156,13 @@
|
|
|
156
156
|
// SVG
|
|
157
157
|
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']);
|
|
158
158
|
|
|
159
|
-
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']);
|
|
159
|
+
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']);
|
|
160
160
|
|
|
161
161
|
// List of SVG elements that are disallowed by default.
|
|
162
162
|
// We still need to know them so that we can do namespace
|
|
163
163
|
// checks properly in case one wants to add them to
|
|
164
164
|
// allow-list.
|
|
165
|
-
var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', '
|
|
165
|
+
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']);
|
|
166
166
|
|
|
167
167
|
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']);
|
|
168
168
|
|
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
|
|
173
173
|
var text = freeze(['#text']);
|
|
174
174
|
|
|
175
|
-
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']);
|
|
175
|
+
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']);
|
|
176
176
|
|
|
177
177
|
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']);
|
|
178
178
|
|
|
@@ -249,7 +249,7 @@
|
|
|
249
249
|
* Version label, exposed for easier checks
|
|
250
250
|
* if DOMPurify is up to date or not
|
|
251
251
|
*/
|
|
252
|
-
DOMPurify.version = '2.3.
|
|
252
|
+
DOMPurify.version = '2.3.4';
|
|
253
253
|
|
|
254
254
|
/**
|
|
255
255
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -275,8 +275,7 @@
|
|
|
275
275
|
NodeFilter = window.NodeFilter,
|
|
276
276
|
_window$NamedNodeMap = window.NamedNodeMap,
|
|
277
277
|
NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
|
|
278
|
-
|
|
279
|
-
Comment = window.Comment,
|
|
278
|
+
HTMLFormElement = window.HTMLFormElement,
|
|
280
279
|
DOMParser = window.DOMParser,
|
|
281
280
|
trustedTypes = window.trustedTypes;
|
|
282
281
|
|
|
@@ -346,6 +345,33 @@
|
|
|
346
345
|
var ALLOWED_ATTR = null;
|
|
347
346
|
var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray$1(html$1), _toConsumableArray$1(svg$1), _toConsumableArray$1(mathMl$1), _toConsumableArray$1(xml)));
|
|
348
347
|
|
|
348
|
+
/*
|
|
349
|
+
* Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.
|
|
350
|
+
* @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
|
|
351
|
+
* @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)
|
|
352
|
+
* @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
|
|
353
|
+
*/
|
|
354
|
+
var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
|
|
355
|
+
tagNameCheck: {
|
|
356
|
+
writable: true,
|
|
357
|
+
configurable: false,
|
|
358
|
+
enumerable: true,
|
|
359
|
+
value: null
|
|
360
|
+
},
|
|
361
|
+
attributeNameCheck: {
|
|
362
|
+
writable: true,
|
|
363
|
+
configurable: false,
|
|
364
|
+
enumerable: true,
|
|
365
|
+
value: null
|
|
366
|
+
},
|
|
367
|
+
allowCustomizedBuiltInElements: {
|
|
368
|
+
writable: true,
|
|
369
|
+
configurable: false,
|
|
370
|
+
enumerable: true,
|
|
371
|
+
value: false
|
|
372
|
+
}
|
|
373
|
+
}));
|
|
374
|
+
|
|
349
375
|
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
|
|
350
376
|
var FORBID_TAGS = null;
|
|
351
377
|
|
|
@@ -386,17 +412,6 @@
|
|
|
386
412
|
* string (or a TrustedHTML object if Trusted Types are supported) */
|
|
387
413
|
var RETURN_DOM_FRAGMENT = false;
|
|
388
414
|
|
|
389
|
-
/* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
|
|
390
|
-
* `Node` is imported into the current `Document`. If this flag is not enabled the
|
|
391
|
-
* `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
|
|
392
|
-
* DOMPurify.
|
|
393
|
-
*
|
|
394
|
-
* This defaults to `true` starting DOMPurify 2.2.0. Note that setting it to `false`
|
|
395
|
-
* might cause XSS from attacks hidden in closed shadowroots in case the browser
|
|
396
|
-
* supports Declarative Shadow: DOM https://web.dev/declarative-shadow-dom/
|
|
397
|
-
*/
|
|
398
|
-
var RETURN_DOM_IMPORT = true;
|
|
399
|
-
|
|
400
415
|
/* Try to return a Trusted Type object instead of a string, return a string in
|
|
401
416
|
* case Trusted Types are not supported */
|
|
402
417
|
var RETURN_TRUSTED_TYPE = false;
|
|
@@ -415,7 +430,8 @@
|
|
|
415
430
|
var USE_PROFILES = {};
|
|
416
431
|
|
|
417
432
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
418
|
-
var FORBID_CONTENTS =
|
|
433
|
+
var FORBID_CONTENTS = null;
|
|
434
|
+
var DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
|
|
419
435
|
|
|
420
436
|
/* Tags that are safe for data: URIs */
|
|
421
437
|
var DATA_URI_TAGS = null;
|
|
@@ -423,7 +439,7 @@
|
|
|
423
439
|
|
|
424
440
|
/* Attributes safe for values like "javascript:" */
|
|
425
441
|
var URI_SAFE_ATTRIBUTES = null;
|
|
426
|
-
var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
|
|
442
|
+
var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
|
|
427
443
|
|
|
428
444
|
var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
|
|
429
445
|
var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
@@ -432,6 +448,12 @@
|
|
|
432
448
|
var NAMESPACE = HTML_NAMESPACE;
|
|
433
449
|
var IS_EMPTY_INPUT = false;
|
|
434
450
|
|
|
451
|
+
/* Parsing of strict XHTML documents */
|
|
452
|
+
var PARSER_MEDIA_TYPE = void 0;
|
|
453
|
+
var SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
|
|
454
|
+
var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
|
|
455
|
+
var transformCaseFunc = void 0;
|
|
456
|
+
|
|
435
457
|
/* Keep a reference to config to pass to hooks */
|
|
436
458
|
var CONFIG = null;
|
|
437
459
|
|
|
@@ -440,6 +462,10 @@
|
|
|
440
462
|
|
|
441
463
|
var formElement = document.createElement('form');
|
|
442
464
|
|
|
465
|
+
var isRegexOrFunction = function isRegexOrFunction(testValue) {
|
|
466
|
+
return testValue instanceof RegExp || testValue instanceof Function;
|
|
467
|
+
};
|
|
468
|
+
|
|
443
469
|
/**
|
|
444
470
|
* _parseConfig
|
|
445
471
|
*
|
|
@@ -464,6 +490,7 @@
|
|
|
464
490
|
ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
|
|
465
491
|
URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
|
|
466
492
|
DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;
|
|
493
|
+
FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS;
|
|
467
494
|
FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
|
|
468
495
|
FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
|
|
469
496
|
USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
|
|
@@ -474,7 +501,6 @@
|
|
|
474
501
|
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
|
|
475
502
|
RETURN_DOM = cfg.RETURN_DOM || false; // Default false
|
|
476
503
|
RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
|
|
477
|
-
RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT !== false; // Default true
|
|
478
504
|
RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
|
|
479
505
|
FORCE_BODY = cfg.FORCE_BODY || false; // Default false
|
|
480
506
|
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
|
@@ -482,6 +508,27 @@
|
|
|
482
508
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
483
509
|
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
484
510
|
NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
|
|
511
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
|
|
512
|
+
CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
|
|
516
|
+
CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
|
|
520
|
+
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
PARSER_MEDIA_TYPE =
|
|
524
|
+
// eslint-disable-next-line unicorn/prefer-includes
|
|
525
|
+
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
|
|
526
|
+
|
|
527
|
+
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
528
|
+
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
|
|
529
|
+
return x;
|
|
530
|
+
} : stringToLowerCase;
|
|
531
|
+
|
|
485
532
|
if (SAFE_FOR_TEMPLATES) {
|
|
486
533
|
ALLOW_DATA_ATTR = false;
|
|
487
534
|
}
|
|
@@ -539,6 +586,14 @@
|
|
|
539
586
|
addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
|
|
540
587
|
}
|
|
541
588
|
|
|
589
|
+
if (cfg.FORBID_CONTENTS) {
|
|
590
|
+
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
591
|
+
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
|
|
595
|
+
}
|
|
596
|
+
|
|
542
597
|
/* Add #text in case KEEP_CONTENT is set to true */
|
|
543
598
|
if (KEEP_CONTENT) {
|
|
544
599
|
ALLOWED_TAGS['#text'] = true;
|
|
@@ -742,6 +797,11 @@
|
|
|
742
797
|
leadingWhitespace = matches && matches[0];
|
|
743
798
|
}
|
|
744
799
|
|
|
800
|
+
if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') {
|
|
801
|
+
// Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
|
|
802
|
+
dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
|
|
803
|
+
}
|
|
804
|
+
|
|
745
805
|
var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
746
806
|
/*
|
|
747
807
|
* Use the DOMParser API by default, fallback later if needs be
|
|
@@ -749,7 +809,7 @@
|
|
|
749
809
|
*/
|
|
750
810
|
if (NAMESPACE === HTML_NAMESPACE) {
|
|
751
811
|
try {
|
|
752
|
-
doc = new DOMParser().parseFromString(dirtyPayload,
|
|
812
|
+
doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
|
|
753
813
|
} catch (_) {}
|
|
754
814
|
}
|
|
755
815
|
|
|
@@ -794,15 +854,7 @@
|
|
|
794
854
|
* @return {Boolean} true if clobbered, false if safe
|
|
795
855
|
*/
|
|
796
856
|
var _isClobbered = function _isClobbered(elm) {
|
|
797
|
-
|
|
798
|
-
return false;
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
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') {
|
|
802
|
-
return true;
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
return false;
|
|
857
|
+
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');
|
|
806
858
|
};
|
|
807
859
|
|
|
808
860
|
/**
|
|
@@ -862,7 +914,7 @@
|
|
|
862
914
|
}
|
|
863
915
|
|
|
864
916
|
/* Now let's check the element's type and name */
|
|
865
|
-
var tagName =
|
|
917
|
+
var tagName = transformCaseFunc(currentNode.nodeName);
|
|
866
918
|
|
|
867
919
|
/* Execute a hook if present */
|
|
868
920
|
_executeHook('uponSanitizeElement', currentNode, {
|
|
@@ -876,6 +928,12 @@
|
|
|
876
928
|
return true;
|
|
877
929
|
}
|
|
878
930
|
|
|
931
|
+
/* Mitigate a problem with templates inside select */
|
|
932
|
+
if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
|
|
933
|
+
_forceRemove(currentNode);
|
|
934
|
+
return true;
|
|
935
|
+
}
|
|
936
|
+
|
|
879
937
|
/* Remove element if anything forbids its presence */
|
|
880
938
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
881
939
|
/* Keep content except for bad-listed elements */
|
|
@@ -892,6 +950,11 @@
|
|
|
892
950
|
}
|
|
893
951
|
}
|
|
894
952
|
|
|
953
|
+
if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
|
|
954
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
|
|
955
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
|
|
956
|
+
}
|
|
957
|
+
|
|
895
958
|
_forceRemove(currentNode);
|
|
896
959
|
return true;
|
|
897
960
|
}
|
|
@@ -945,8 +1008,16 @@
|
|
|
945
1008
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
946
1009
|
We don't need to check the value; it's always URI safe. */
|
|
947
1010
|
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]) {
|
|
948
|
-
|
|
949
|
-
|
|
1011
|
+
if (
|
|
1012
|
+
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
1013
|
+
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1014
|
+
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
|
|
1015
|
+
_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)) ||
|
|
1016
|
+
// Alternative, second condition checks if it's an `is`-attribute, AND
|
|
1017
|
+
// the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1018
|
+
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 {
|
|
1019
|
+
return false;
|
|
1020
|
+
}
|
|
950
1021
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
951
1022
|
} 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 {
|
|
952
1023
|
return false;
|
|
@@ -955,6 +1026,16 @@
|
|
|
955
1026
|
return true;
|
|
956
1027
|
};
|
|
957
1028
|
|
|
1029
|
+
/**
|
|
1030
|
+
* _basicCustomElementCheck
|
|
1031
|
+
* checks if at least one dash is included in tagName, and it's not the first char
|
|
1032
|
+
* for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
|
|
1033
|
+
* @param {string} tagName name of the tag of the node to sanitize
|
|
1034
|
+
*/
|
|
1035
|
+
var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
|
|
1036
|
+
return tagName.indexOf('-') > 0;
|
|
1037
|
+
};
|
|
1038
|
+
|
|
958
1039
|
/**
|
|
959
1040
|
* _sanitizeAttributes
|
|
960
1041
|
*
|
|
@@ -997,7 +1078,7 @@
|
|
|
997
1078
|
namespaceURI = _attr.namespaceURI;
|
|
998
1079
|
|
|
999
1080
|
value = stringTrim(attr.value);
|
|
1000
|
-
lcName =
|
|
1081
|
+
lcName = transformCaseFunc(name);
|
|
1001
1082
|
|
|
1002
1083
|
/* Execute a hook if present */
|
|
1003
1084
|
hookEvent.attrName = lcName;
|
|
@@ -1032,7 +1113,7 @@
|
|
|
1032
1113
|
}
|
|
1033
1114
|
|
|
1034
1115
|
/* Is `value` valid for this attribute? */
|
|
1035
|
-
var lcTag = currentNode.nodeName
|
|
1116
|
+
var lcTag = transformCaseFunc(currentNode.nodeName);
|
|
1036
1117
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
1037
1118
|
continue;
|
|
1038
1119
|
}
|
|
@@ -1233,7 +1314,7 @@
|
|
|
1233
1314
|
returnNode = body;
|
|
1234
1315
|
}
|
|
1235
1316
|
|
|
1236
|
-
if (
|
|
1317
|
+
if (ALLOWED_ATTR.shadowroot) {
|
|
1237
1318
|
/*
|
|
1238
1319
|
AdoptNode() is not used because internal state is not reset
|
|
1239
1320
|
(e.g. the past names map of a HTMLFormElement), this is safe
|
|
@@ -1295,8 +1376,8 @@
|
|
|
1295
1376
|
_parseConfig({});
|
|
1296
1377
|
}
|
|
1297
1378
|
|
|
1298
|
-
var lcTag =
|
|
1299
|
-
var lcName =
|
|
1379
|
+
var lcTag = transformCaseFunc(tag);
|
|
1380
|
+
var lcName = transformCaseFunc(attr);
|
|
1300
1381
|
return _isValidAttribute(lcTag, lcName, value);
|
|
1301
1382
|
};
|
|
1302
1383
|
|