@vaadin/bundles 24.9.12 → 24.9.14

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.
@@ -10,7 +10,7 @@ __webpack_require__.r(__webpack_exports__);
10
10
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
11
11
  /* harmony export */ "default": () => (/* binding */ purify)
12
12
  /* harmony export */ });
13
- /*! @license DOMPurify 3.2.7 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.7/LICENSE */
13
+ /*! @license DOMPurify 3.4.0 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.0/LICENSE */
14
14
 
15
15
  const {
16
16
  entries,
@@ -196,7 +196,7 @@ function lookupGetter(object, prop) {
196
196
  }
197
197
 
198
198
  const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
199
- const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'slot', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
199
+ const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
200
200
  const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
201
201
  // List of SVG elements that are disallowed by default.
202
202
  // We still need to know them so that we can do namespace
@@ -210,8 +210,8 @@ const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongd
210
210
  const text = freeze(['#text']);
211
211
 
212
212
  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', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', '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', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);
213
- const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', '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', 'exponent', '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', 'intercept', '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', 'slope', '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', 'tablevalues', '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']);
214
- 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']);
213
+ const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', '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', 'exponent', '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', 'intercept', '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', 'mask-type', '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', 'slope', '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', 'tablevalues', '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']);
214
+ const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnalign', 'columnlines', 'columnspacing', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lquote', 'lspace', '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']);
215
215
  const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
216
216
 
217
217
  // eslint-disable-next-line unicorn/better-regex
@@ -246,20 +246,11 @@ var EXPRESSIONS = /*#__PURE__*/Object.freeze({
246
246
  // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
247
247
  const NODE_TYPE = {
248
248
  element: 1,
249
- attribute: 2,
250
249
  text: 3,
251
- cdataSection: 4,
252
- entityReference: 5,
253
- // Deprecated
254
- entityNode: 6,
255
250
  // Deprecated
256
251
  progressingInstruction: 7,
257
252
  comment: 8,
258
- document: 9,
259
- documentType: 10,
260
- documentFragment: 11,
261
- notation: 12 // Deprecated
262
- };
253
+ document: 9};
263
254
  const getGlobal = function getGlobal() {
264
255
  return typeof window === 'undefined' ? null : window;
265
256
  };
@@ -317,7 +308,7 @@ const _createHooksMap = function _createHooksMap() {
317
308
  function createDOMPurify() {
318
309
  let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
319
310
  const DOMPurify = root => createDOMPurify(root);
320
- DOMPurify.version = '3.2.7';
311
+ DOMPurify.version = '3.4.0';
321
312
  DOMPurify.removed = [];
322
313
  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
323
314
  // Not running in a browser, provide a factory function
@@ -428,6 +419,21 @@ function createDOMPurify() {
428
419
  let FORBID_TAGS = null;
429
420
  /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
430
421
  let FORBID_ATTR = null;
422
+ /* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */
423
+ const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {
424
+ tagCheck: {
425
+ writable: true,
426
+ configurable: false,
427
+ enumerable: true,
428
+ value: null
429
+ },
430
+ attributeCheck: {
431
+ writable: true,
432
+ configurable: false,
433
+ enumerable: true,
434
+ value: null
435
+ }
436
+ }));
431
437
  /* Decide if ARIA attributes are okay */
432
438
  let ALLOW_ARIA_ATTR = true;
433
439
  /* Decide if custom data attributes are okay */
@@ -578,7 +584,7 @@ function createDOMPurify() {
578
584
  NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
579
585
  MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;
580
586
  HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;
581
- CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
587
+ CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || create(null);
582
588
  if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
583
589
  CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
584
590
  }
@@ -597,7 +603,7 @@ function createDOMPurify() {
597
603
  /* Parse profile info */
598
604
  if (USE_PROFILES) {
599
605
  ALLOWED_TAGS = addToSet({}, text);
600
- ALLOWED_ATTR = [];
606
+ ALLOWED_ATTR = create(null);
601
607
  if (USE_PROFILES.html === true) {
602
608
  addToSet(ALLOWED_TAGS, html$1);
603
609
  addToSet(ALLOWED_ATTR, html);
@@ -618,18 +624,30 @@ function createDOMPurify() {
618
624
  addToSet(ALLOWED_ATTR, xml);
619
625
  }
620
626
  }
627
+ /* Always reset function-based ADD_TAGS / ADD_ATTR checks to prevent
628
+ * leaking across calls when switching from function to array config */
629
+ EXTRA_ELEMENT_HANDLING.tagCheck = null;
630
+ EXTRA_ELEMENT_HANDLING.attributeCheck = null;
621
631
  /* Merge configuration parameters */
622
632
  if (cfg.ADD_TAGS) {
623
- if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
624
- ALLOWED_TAGS = clone(ALLOWED_TAGS);
633
+ if (typeof cfg.ADD_TAGS === 'function') {
634
+ EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
635
+ } else {
636
+ if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
637
+ ALLOWED_TAGS = clone(ALLOWED_TAGS);
638
+ }
639
+ addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
625
640
  }
626
- addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
627
641
  }
628
642
  if (cfg.ADD_ATTR) {
629
- if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
630
- ALLOWED_ATTR = clone(ALLOWED_ATTR);
643
+ if (typeof cfg.ADD_ATTR === 'function') {
644
+ EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
645
+ } else {
646
+ if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
647
+ ALLOWED_ATTR = clone(ALLOWED_ATTR);
648
+ }
649
+ addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
631
650
  }
632
- addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
633
651
  }
634
652
  if (cfg.ADD_URI_SAFE_ATTR) {
635
653
  addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
@@ -640,6 +658,12 @@ function createDOMPurify() {
640
658
  }
641
659
  addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
642
660
  }
661
+ if (cfg.ADD_FORBID_CONTENTS) {
662
+ if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
663
+ FORBID_CONTENTS = clone(FORBID_CONTENTS);
664
+ }
665
+ addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
666
+ }
643
667
  /* Add #text in case KEEP_CONTENT is set to true */
644
668
  if (KEEP_CONTENT) {
645
669
  ALLOWED_TAGS['#text'] = true;
@@ -926,6 +950,11 @@ function createDOMPurify() {
926
950
  _forceRemove(currentNode);
927
951
  return true;
928
952
  }
953
+ /* Remove risky CSS construction leading to mXSS */
954
+ if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === 'style' && _isNode(currentNode.firstElementChild)) {
955
+ _forceRemove(currentNode);
956
+ return true;
957
+ }
929
958
  /* Remove any occurrence of processing instructions */
930
959
  if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
931
960
  _forceRemove(currentNode);
@@ -937,7 +966,7 @@ function createDOMPurify() {
937
966
  return true;
938
967
  }
939
968
  /* Remove element if anything forbids its presence */
940
- if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
969
+ if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
941
970
  /* Check if we have a custom element to handle */
942
971
  if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
943
972
  if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
@@ -1001,6 +1030,10 @@ function createDOMPurify() {
1001
1030
  */
1002
1031
  // eslint-disable-next-line complexity
1003
1032
  const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1033
+ /* FORBID_ATTR must always win, even if ADD_ATTR predicate would allow it */
1034
+ if (FORBID_ATTR[lcName]) {
1035
+ return false;
1036
+ }
1004
1037
  /* Make sure attribute cannot clobber */
1005
1038
  if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1006
1039
  return false;
@@ -1009,7 +1042,7 @@ function createDOMPurify() {
1009
1042
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
1010
1043
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
1011
1044
  We don't need to check the value; it's always URI safe. */
1012
- if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
1045
+ if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
1013
1046
  if (
1014
1047
  // First condition does a very basic check if a) it's basically a valid custom element tagname AND
1015
1048
  // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
@@ -1093,7 +1126,7 @@ function createDOMPurify() {
1093
1126
  value = SANITIZE_NAMED_PROPS_PREFIX + value;
1094
1127
  }
1095
1128
  /* Work around a security issue with comments inside attributes */
1096
- if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title|textarea)/i, value)) {
1129
+ if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
1097
1130
  _removeAttribute(name, currentNode);
1098
1131
  continue;
1099
1132
  }
@@ -1172,7 +1205,7 @@ function createDOMPurify() {
1172
1205
  *
1173
1206
  * @param fragment to iterate over recursively
1174
1207
  */
1175
- const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
1208
+ const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
1176
1209
  let shadowNode = null;
1177
1210
  const shadowIterator = _createNodeIterator(fragment);
1178
1211
  /* Execute a hook if present */
@@ -1186,7 +1219,7 @@ function createDOMPurify() {
1186
1219
  _sanitizeAttributes(shadowNode);
1187
1220
  /* Deep shadow DOM detected */
1188
1221
  if (shadowNode.content instanceof DocumentFragment) {
1189
- _sanitizeShadowDOM(shadowNode.content);
1222
+ _sanitizeShadowDOM2(shadowNode.content);
1190
1223
  }
1191
1224
  }
1192
1225
  /* Execute a hook if present */
@@ -1281,7 +1314,7 @@ function createDOMPurify() {
1281
1314
  _sanitizeAttributes(currentNode);
1282
1315
  /* Shadow DOM detected, sanitize it */
1283
1316
  if (currentNode.content instanceof DocumentFragment) {
1284
- _sanitizeShadowDOM(currentNode.content);
1317
+ _sanitizeShadowDOM2(currentNode.content);
1285
1318
  }
1286
1319
  }
1287
1320
  /* If we sanitized `dirty` in-place, return it. */
@@ -1290,6 +1323,14 @@ function createDOMPurify() {
1290
1323
  }
1291
1324
  /* Return sanitized string or DOM */
1292
1325
  if (RETURN_DOM) {
1326
+ if (SAFE_FOR_TEMPLATES) {
1327
+ body.normalize();
1328
+ let html = body.innerHTML;
1329
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
1330
+ html = stringReplace(html, expr, ' ');
1331
+ });
1332
+ body.innerHTML = html;
1333
+ }
1293
1334
  if (RETURN_DOM_FRAGMENT) {
1294
1335
  returnNode = createDocumentFragment.call(body.ownerDocument);
1295
1336
  while (body.firstChild) {