@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.
@@ -6,7 +6,7 @@
6
6
  \***********************************************/
7
7
  /***/ (function(module) {
8
8
 
9
- /*! @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 */
9
+ /*! @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 */
10
10
 
11
11
  (function (global, factory) {
12
12
  true ? module.exports = factory() :
@@ -197,7 +197,7 @@
197
197
  }
198
198
 
199
199
  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']);
200
- 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']);
200
+ 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']);
201
201
  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']);
202
202
  // List of SVG elements that are disallowed by default.
203
203
  // We still need to know them so that we can do namespace
@@ -211,8 +211,8 @@
211
211
  const text = freeze(['#text']);
212
212
 
213
213
  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']);
214
- 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']);
215
- 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']);
214
+ 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']);
215
+ 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']);
216
216
  const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
217
217
 
218
218
  // eslint-disable-next-line unicorn/better-regex
@@ -247,20 +247,11 @@
247
247
  // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
248
248
  const NODE_TYPE = {
249
249
  element: 1,
250
- attribute: 2,
251
250
  text: 3,
252
- cdataSection: 4,
253
- entityReference: 5,
254
- // Deprecated
255
- entityNode: 6,
256
251
  // Deprecated
257
252
  progressingInstruction: 7,
258
253
  comment: 8,
259
- document: 9,
260
- documentType: 10,
261
- documentFragment: 11,
262
- notation: 12 // Deprecated
263
- };
254
+ document: 9};
264
255
  const getGlobal = function getGlobal() {
265
256
  return typeof window === 'undefined' ? null : window;
266
257
  };
@@ -318,7 +309,7 @@
318
309
  function createDOMPurify() {
319
310
  let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
320
311
  const DOMPurify = root => createDOMPurify(root);
321
- DOMPurify.version = '3.2.7';
312
+ DOMPurify.version = '3.4.0';
322
313
  DOMPurify.removed = [];
323
314
  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
324
315
  // Not running in a browser, provide a factory function
@@ -429,6 +420,21 @@
429
420
  let FORBID_TAGS = null;
430
421
  /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
431
422
  let FORBID_ATTR = null;
423
+ /* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */
424
+ const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {
425
+ tagCheck: {
426
+ writable: true,
427
+ configurable: false,
428
+ enumerable: true,
429
+ value: null
430
+ },
431
+ attributeCheck: {
432
+ writable: true,
433
+ configurable: false,
434
+ enumerable: true,
435
+ value: null
436
+ }
437
+ }));
432
438
  /* Decide if ARIA attributes are okay */
433
439
  let ALLOW_ARIA_ATTR = true;
434
440
  /* Decide if custom data attributes are okay */
@@ -579,7 +585,7 @@
579
585
  NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
580
586
  MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;
581
587
  HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;
582
- CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
588
+ CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || create(null);
583
589
  if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
584
590
  CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
585
591
  }
@@ -598,7 +604,7 @@
598
604
  /* Parse profile info */
599
605
  if (USE_PROFILES) {
600
606
  ALLOWED_TAGS = addToSet({}, text);
601
- ALLOWED_ATTR = [];
607
+ ALLOWED_ATTR = create(null);
602
608
  if (USE_PROFILES.html === true) {
603
609
  addToSet(ALLOWED_TAGS, html$1);
604
610
  addToSet(ALLOWED_ATTR, html);
@@ -619,18 +625,30 @@
619
625
  addToSet(ALLOWED_ATTR, xml);
620
626
  }
621
627
  }
628
+ /* Always reset function-based ADD_TAGS / ADD_ATTR checks to prevent
629
+ * leaking across calls when switching from function to array config */
630
+ EXTRA_ELEMENT_HANDLING.tagCheck = null;
631
+ EXTRA_ELEMENT_HANDLING.attributeCheck = null;
622
632
  /* Merge configuration parameters */
623
633
  if (cfg.ADD_TAGS) {
624
- if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
625
- ALLOWED_TAGS = clone(ALLOWED_TAGS);
634
+ if (typeof cfg.ADD_TAGS === 'function') {
635
+ EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
636
+ } else {
637
+ if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
638
+ ALLOWED_TAGS = clone(ALLOWED_TAGS);
639
+ }
640
+ addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
626
641
  }
627
- addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
628
642
  }
629
643
  if (cfg.ADD_ATTR) {
630
- if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
631
- ALLOWED_ATTR = clone(ALLOWED_ATTR);
644
+ if (typeof cfg.ADD_ATTR === 'function') {
645
+ EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
646
+ } else {
647
+ if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
648
+ ALLOWED_ATTR = clone(ALLOWED_ATTR);
649
+ }
650
+ addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
632
651
  }
633
- addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
634
652
  }
635
653
  if (cfg.ADD_URI_SAFE_ATTR) {
636
654
  addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
@@ -641,6 +659,12 @@
641
659
  }
642
660
  addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
643
661
  }
662
+ if (cfg.ADD_FORBID_CONTENTS) {
663
+ if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
664
+ FORBID_CONTENTS = clone(FORBID_CONTENTS);
665
+ }
666
+ addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
667
+ }
644
668
  /* Add #text in case KEEP_CONTENT is set to true */
645
669
  if (KEEP_CONTENT) {
646
670
  ALLOWED_TAGS['#text'] = true;
@@ -927,6 +951,11 @@
927
951
  _forceRemove(currentNode);
928
952
  return true;
929
953
  }
954
+ /* Remove risky CSS construction leading to mXSS */
955
+ if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === 'style' && _isNode(currentNode.firstElementChild)) {
956
+ _forceRemove(currentNode);
957
+ return true;
958
+ }
930
959
  /* Remove any occurrence of processing instructions */
931
960
  if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
932
961
  _forceRemove(currentNode);
@@ -938,7 +967,7 @@
938
967
  return true;
939
968
  }
940
969
  /* Remove element if anything forbids its presence */
941
- if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
970
+ if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
942
971
  /* Check if we have a custom element to handle */
943
972
  if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
944
973
  if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
@@ -1002,6 +1031,10 @@
1002
1031
  */
1003
1032
  // eslint-disable-next-line complexity
1004
1033
  const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1034
+ /* FORBID_ATTR must always win, even if ADD_ATTR predicate would allow it */
1035
+ if (FORBID_ATTR[lcName]) {
1036
+ return false;
1037
+ }
1005
1038
  /* Make sure attribute cannot clobber */
1006
1039
  if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1007
1040
  return false;
@@ -1010,7 +1043,7 @@
1010
1043
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
1011
1044
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
1012
1045
  We don't need to check the value; it's always URI safe. */
1013
- 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]) {
1046
+ 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]) {
1014
1047
  if (
1015
1048
  // First condition does a very basic check if a) it's basically a valid custom element tagname AND
1016
1049
  // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
@@ -1094,7 +1127,7 @@
1094
1127
  value = SANITIZE_NAMED_PROPS_PREFIX + value;
1095
1128
  }
1096
1129
  /* Work around a security issue with comments inside attributes */
1097
- if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title|textarea)/i, value)) {
1130
+ if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
1098
1131
  _removeAttribute(name, currentNode);
1099
1132
  continue;
1100
1133
  }
@@ -1173,7 +1206,7 @@
1173
1206
  *
1174
1207
  * @param fragment to iterate over recursively
1175
1208
  */
1176
- const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
1209
+ const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
1177
1210
  let shadowNode = null;
1178
1211
  const shadowIterator = _createNodeIterator(fragment);
1179
1212
  /* Execute a hook if present */
@@ -1187,7 +1220,7 @@
1187
1220
  _sanitizeAttributes(shadowNode);
1188
1221
  /* Deep shadow DOM detected */
1189
1222
  if (shadowNode.content instanceof DocumentFragment) {
1190
- _sanitizeShadowDOM(shadowNode.content);
1223
+ _sanitizeShadowDOM2(shadowNode.content);
1191
1224
  }
1192
1225
  }
1193
1226
  /* Execute a hook if present */
@@ -1282,7 +1315,7 @@
1282
1315
  _sanitizeAttributes(currentNode);
1283
1316
  /* Shadow DOM detected, sanitize it */
1284
1317
  if (currentNode.content instanceof DocumentFragment) {
1285
- _sanitizeShadowDOM(currentNode.content);
1318
+ _sanitizeShadowDOM2(currentNode.content);
1286
1319
  }
1287
1320
  }
1288
1321
  /* If we sanitized `dirty` in-place, return it. */
@@ -1291,6 +1324,14 @@
1291
1324
  }
1292
1325
  /* Return sanitized string or DOM */
1293
1326
  if (RETURN_DOM) {
1327
+ if (SAFE_FOR_TEMPLATES) {
1328
+ body.normalize();
1329
+ let html = body.innerHTML;
1330
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
1331
+ html = stringReplace(html, expr, ' ');
1332
+ });
1333
+ body.innerHTML = html;
1334
+ }
1294
1335
  if (RETURN_DOM_FRAGMENT) {
1295
1336
  returnNode = createDocumentFragment.call(body.ownerDocument);
1296
1337
  while (body.firstChild) {