dompurify 2.2.4 → 2.2.8
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 +7 -2
- package/dist/purify.cjs.js +210 -34
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +210 -34
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +210 -34
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +1 -1
- package/dist/purify.min.js.map +1 -1
- package/package.json +1 -1
package/dist/purify.es.js
CHANGED
|
@@ -4,7 +4,9 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr
|
|
|
4
4
|
|
|
5
5
|
var hasOwnProperty = Object.hasOwnProperty,
|
|
6
6
|
setPrototypeOf = Object.setPrototypeOf,
|
|
7
|
-
isFrozen = Object.isFrozen
|
|
7
|
+
isFrozen = Object.isFrozen,
|
|
8
|
+
getPrototypeOf = Object.getPrototypeOf,
|
|
9
|
+
getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
8
10
|
var freeze = Object.freeze,
|
|
9
11
|
seal = Object.seal,
|
|
10
12
|
create = Object.create; // eslint-disable-line import/no-mutable-exports
|
|
@@ -115,18 +117,56 @@ function clone(object) {
|
|
|
115
117
|
return newObject;
|
|
116
118
|
}
|
|
117
119
|
|
|
120
|
+
/* IE10 doesn't support __lookupGetter__ so lets'
|
|
121
|
+
* simulate it. It also automatically checks
|
|
122
|
+
* if the prop is function or getter and behaves
|
|
123
|
+
* accordingly. */
|
|
124
|
+
function lookupGetter(object, prop) {
|
|
125
|
+
while (object !== null) {
|
|
126
|
+
var desc = getOwnPropertyDescriptor(object, prop);
|
|
127
|
+
if (desc) {
|
|
128
|
+
if (desc.get) {
|
|
129
|
+
return unapply(desc.get);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (typeof desc.value === 'function') {
|
|
133
|
+
return unapply(desc.value);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
object = getPrototypeOf(object);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function fallbackValue(element) {
|
|
141
|
+
console.warn('fallback value for', element);
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return fallbackValue;
|
|
146
|
+
}
|
|
147
|
+
|
|
118
148
|
var html = 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', 'section', 'select', 'shadow', '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']);
|
|
119
149
|
|
|
120
150
|
// SVG
|
|
121
|
-
var svg = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', '
|
|
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']);
|
|
122
152
|
|
|
123
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']);
|
|
124
154
|
|
|
155
|
+
// List of SVG elements that are disallowed by default.
|
|
156
|
+
// We still need to know them so that we can do namespace
|
|
157
|
+
// checks properly in case one wants to add them to
|
|
158
|
+
// allow-list.
|
|
159
|
+
var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', 'feimage', '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
|
+
|
|
125
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']);
|
|
126
162
|
|
|
163
|
+
// Similarly to SVG, we want to know all MathML elements,
|
|
164
|
+
// even those that we disallow by default.
|
|
165
|
+
var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
166
|
+
|
|
127
167
|
var text = freeze(['#text']);
|
|
128
168
|
|
|
129
|
-
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']);
|
|
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']);
|
|
130
170
|
|
|
131
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']);
|
|
132
172
|
|
|
@@ -203,7 +243,7 @@ function createDOMPurify() {
|
|
|
203
243
|
* Version label, exposed for easier checks
|
|
204
244
|
* if DOMPurify is up to date or not
|
|
205
245
|
*/
|
|
206
|
-
DOMPurify.version = '2.2.
|
|
246
|
+
DOMPurify.version = '2.2.8';
|
|
207
247
|
|
|
208
248
|
/**
|
|
209
249
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -225,6 +265,7 @@ function createDOMPurify() {
|
|
|
225
265
|
var DocumentFragment = window.DocumentFragment,
|
|
226
266
|
HTMLTemplateElement = window.HTMLTemplateElement,
|
|
227
267
|
Node = window.Node,
|
|
268
|
+
Element = window.Element,
|
|
228
269
|
NodeFilter = window.NodeFilter,
|
|
229
270
|
_window$NamedNodeMap = window.NamedNodeMap,
|
|
230
271
|
NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
|
|
@@ -233,13 +274,20 @@ function createDOMPurify() {
|
|
|
233
274
|
DOMParser = window.DOMParser,
|
|
234
275
|
trustedTypes = window.trustedTypes;
|
|
235
276
|
|
|
277
|
+
|
|
278
|
+
var ElementPrototype = Element.prototype;
|
|
279
|
+
|
|
280
|
+
var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
|
|
281
|
+
var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
|
|
282
|
+
var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
|
|
283
|
+
var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
|
|
284
|
+
|
|
236
285
|
// As per issue #47, the web-components registry is inherited by a
|
|
237
286
|
// new document created via createHTMLDocument. As per the spec
|
|
238
287
|
// (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
|
|
239
288
|
// a new empty registry is used when creating a template contents owner
|
|
240
289
|
// document, so we use that as our parent document to ensure nothing
|
|
241
290
|
// is inherited.
|
|
242
|
-
|
|
243
291
|
if (typeof HTMLTemplateElement === 'function') {
|
|
244
292
|
var template = document.createElement('template');
|
|
245
293
|
if (template.content && template.content.ownerDocument) {
|
|
@@ -253,7 +301,6 @@ function createDOMPurify() {
|
|
|
253
301
|
var _document = document,
|
|
254
302
|
implementation = _document.implementation,
|
|
255
303
|
createNodeIterator = _document.createNodeIterator,
|
|
256
|
-
getElementsByTagName = _document.getElementsByTagName,
|
|
257
304
|
createDocumentFragment = _document.createDocumentFragment;
|
|
258
305
|
var importNode = originalDocument.importNode;
|
|
259
306
|
|
|
@@ -268,7 +315,7 @@ function createDOMPurify() {
|
|
|
268
315
|
/**
|
|
269
316
|
* Expose whether this browser supports running the full DOMPurify.
|
|
270
317
|
*/
|
|
271
|
-
DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
|
|
318
|
+
DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
|
|
272
319
|
|
|
273
320
|
var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
|
|
274
321
|
ERB_EXPR$$1 = ERB_EXPR,
|
|
@@ -361,7 +408,7 @@ function createDOMPurify() {
|
|
|
361
408
|
var USE_PROFILES = {};
|
|
362
409
|
|
|
363
410
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
364
|
-
var FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
|
|
411
|
+
var 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']);
|
|
365
412
|
|
|
366
413
|
/* Tags that are safe for data: URIs */
|
|
367
414
|
var DATA_URI_TAGS = null;
|
|
@@ -371,6 +418,12 @@ function createDOMPurify() {
|
|
|
371
418
|
var URI_SAFE_ATTRIBUTES = null;
|
|
372
419
|
var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
|
|
373
420
|
|
|
421
|
+
var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
|
|
422
|
+
var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
423
|
+
var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
|
|
424
|
+
/* Document namespace */
|
|
425
|
+
var NAMESPACE = HTML_NAMESPACE;
|
|
426
|
+
|
|
374
427
|
/* Keep a reference to config to pass to hooks */
|
|
375
428
|
var CONFIG = null;
|
|
376
429
|
|
|
@@ -420,6 +473,7 @@ function createDOMPurify() {
|
|
|
420
473
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
421
474
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
422
475
|
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
476
|
+
NAMESPACE = cfg.NAMESPACE || NAMESPACE;
|
|
423
477
|
if (SAFE_FOR_TEMPLATES) {
|
|
424
478
|
ALLOW_DATA_ATTR = false;
|
|
425
479
|
}
|
|
@@ -502,6 +556,111 @@ function createDOMPurify() {
|
|
|
502
556
|
CONFIG = cfg;
|
|
503
557
|
};
|
|
504
558
|
|
|
559
|
+
var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
|
|
560
|
+
|
|
561
|
+
var HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']);
|
|
562
|
+
|
|
563
|
+
/* Keep track of all possible SVG and MathML tags
|
|
564
|
+
* so that we can perform the namespace checks
|
|
565
|
+
* correctly. */
|
|
566
|
+
var ALL_SVG_TAGS = addToSet({}, svg);
|
|
567
|
+
addToSet(ALL_SVG_TAGS, svgFilters);
|
|
568
|
+
addToSet(ALL_SVG_TAGS, svgDisallowed);
|
|
569
|
+
|
|
570
|
+
var ALL_MATHML_TAGS = addToSet({}, mathMl);
|
|
571
|
+
addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
*
|
|
575
|
+
*
|
|
576
|
+
* @param {Element} element a DOM element whose namespace is being checked
|
|
577
|
+
* @returns {boolean} Return false if the element has a
|
|
578
|
+
* namespace that a spec-compliant parser would never
|
|
579
|
+
* return. Return true otherwise.
|
|
580
|
+
*/
|
|
581
|
+
var _checkValidNamespace = function _checkValidNamespace(element) {
|
|
582
|
+
var parent = getParentNode(element);
|
|
583
|
+
|
|
584
|
+
// In JSDOM, if we're inside shadow DOM, then parentNode
|
|
585
|
+
// can be null. We just simulate parent in this case.
|
|
586
|
+
if (!parent || !parent.tagName) {
|
|
587
|
+
parent = {
|
|
588
|
+
namespaceURI: HTML_NAMESPACE,
|
|
589
|
+
tagName: 'template'
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
var tagName = stringToLowerCase(element.tagName);
|
|
594
|
+
var parentTagName = stringToLowerCase(parent.tagName);
|
|
595
|
+
|
|
596
|
+
if (element.namespaceURI === SVG_NAMESPACE) {
|
|
597
|
+
// The only way to switch from HTML namespace to SVG
|
|
598
|
+
// is via <svg>. If it happens via any other tag, then
|
|
599
|
+
// it should be killed.
|
|
600
|
+
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
601
|
+
return tagName === 'svg';
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// The only way to switch from MathML to SVG is via
|
|
605
|
+
// svg if parent is either <annotation-xml> or MathML
|
|
606
|
+
// text integration points.
|
|
607
|
+
if (parent.namespaceURI === MATHML_NAMESPACE) {
|
|
608
|
+
return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// We only allow elements that are defined in SVG
|
|
612
|
+
// spec. All others are disallowed in SVG namespace.
|
|
613
|
+
return Boolean(ALL_SVG_TAGS[tagName]);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (element.namespaceURI === MATHML_NAMESPACE) {
|
|
617
|
+
// The only way to switch from HTML namespace to MathML
|
|
618
|
+
// is via <math>. If it happens via any other tag, then
|
|
619
|
+
// it should be killed.
|
|
620
|
+
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
621
|
+
return tagName === 'math';
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// The only way to switch from SVG to MathML is via
|
|
625
|
+
// <math> and HTML integration points
|
|
626
|
+
if (parent.namespaceURI === SVG_NAMESPACE) {
|
|
627
|
+
return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// We only allow elements that are defined in MathML
|
|
631
|
+
// spec. All others are disallowed in MathML namespace.
|
|
632
|
+
return Boolean(ALL_MATHML_TAGS[tagName]);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
if (element.namespaceURI === HTML_NAMESPACE) {
|
|
636
|
+
// The only way to switch from SVG to HTML is via
|
|
637
|
+
// HTML integration points, and from MathML to HTML
|
|
638
|
+
// is via MathML text integration points
|
|
639
|
+
if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
|
|
640
|
+
return false;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// Certain elements are allowed in both SVG and HTML
|
|
648
|
+
// namespace. We need to specify them explicitly
|
|
649
|
+
// so that they don't get erronously deleted from
|
|
650
|
+
// HTML namespace.
|
|
651
|
+
var commonSvgAndHTMLElements = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
|
|
652
|
+
|
|
653
|
+
// We disallow tags that are specific for MathML
|
|
654
|
+
// or SVG and should never appear in HTML namespace
|
|
655
|
+
return !ALL_MATHML_TAGS[tagName] && (commonSvgAndHTMLElements[tagName] || !ALL_SVG_TAGS[tagName]);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// The code should never reach this place (this means
|
|
659
|
+
// that the element somehow got namespace that is not
|
|
660
|
+
// HTML, SVG or MathML). Return false just in case.
|
|
661
|
+
return false;
|
|
662
|
+
};
|
|
663
|
+
|
|
505
664
|
/**
|
|
506
665
|
* _forceRemove
|
|
507
666
|
*
|
|
@@ -540,6 +699,19 @@ function createDOMPurify() {
|
|
|
540
699
|
}
|
|
541
700
|
|
|
542
701
|
node.removeAttribute(name);
|
|
702
|
+
|
|
703
|
+
// We void attribute values for unremovable "is"" attributes
|
|
704
|
+
if (name === 'is' && !ALLOWED_ATTR[name]) {
|
|
705
|
+
if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
|
|
706
|
+
try {
|
|
707
|
+
_forceRemove(node);
|
|
708
|
+
} catch (_) {}
|
|
709
|
+
} else {
|
|
710
|
+
try {
|
|
711
|
+
node.setAttribute(name, '');
|
|
712
|
+
} catch (_) {}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
543
715
|
};
|
|
544
716
|
|
|
545
717
|
/**
|
|
@@ -562,27 +734,30 @@ function createDOMPurify() {
|
|
|
562
734
|
}
|
|
563
735
|
|
|
564
736
|
var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
565
|
-
/*
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
737
|
+
/*
|
|
738
|
+
* Use the DOMParser API by default, fallback later if needs be
|
|
739
|
+
* DOMParser not work for svg when has multiple root element.
|
|
740
|
+
*/
|
|
741
|
+
if (NAMESPACE === HTML_NAMESPACE) {
|
|
742
|
+
try {
|
|
743
|
+
doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
|
|
744
|
+
} catch (_) {}
|
|
745
|
+
}
|
|
569
746
|
|
|
570
747
|
/* Use createHTMLDocument in case DOMParser is not available */
|
|
571
748
|
if (!doc || !doc.documentElement) {
|
|
572
|
-
doc = implementation.
|
|
573
|
-
|
|
574
|
-
body = _doc.body;
|
|
575
|
-
|
|
576
|
-
body.parentNode.removeChild(body.parentNode.firstElementChild);
|
|
577
|
-
body.outerHTML = dirtyPayload;
|
|
749
|
+
doc = implementation.createDocument(NAMESPACE, 'template', null);
|
|
750
|
+
doc.documentElement.innerHTML = dirtyPayload;
|
|
578
751
|
}
|
|
579
752
|
|
|
753
|
+
var body = doc.body || doc.documentElement;
|
|
754
|
+
|
|
580
755
|
if (dirty && leadingWhitespace) {
|
|
581
|
-
|
|
756
|
+
body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
|
|
582
757
|
}
|
|
583
758
|
|
|
584
759
|
/* Work on whole document or just its body */
|
|
585
|
-
return
|
|
760
|
+
return WHOLE_DOCUMENT ? doc.documentElement : body;
|
|
586
761
|
};
|
|
587
762
|
|
|
588
763
|
/**
|
|
@@ -608,7 +783,7 @@ function createDOMPurify() {
|
|
|
608
783
|
return false;
|
|
609
784
|
}
|
|
610
785
|
|
|
611
|
-
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') {
|
|
786
|
+
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') {
|
|
612
787
|
return true;
|
|
613
788
|
}
|
|
614
789
|
|
|
@@ -689,29 +864,30 @@ function createDOMPurify() {
|
|
|
689
864
|
/* Remove element if anything forbids its presence */
|
|
690
865
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
691
866
|
/* Keep content except for bad-listed elements */
|
|
692
|
-
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);
|
|
696
|
-
} catch (_) {}
|
|
697
|
-
}
|
|
867
|
+
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
868
|
+
var parentNode = getParentNode(currentNode) || currentNode.parentNode;
|
|
869
|
+
var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
|
|
698
870
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
871
|
+
if (childNodes && parentNode) {
|
|
872
|
+
var childCount = childNodes.length;
|
|
873
|
+
|
|
874
|
+
for (var i = childCount - 1; i >= 0; --i) {
|
|
875
|
+
parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
702
879
|
|
|
703
|
-
if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
|
|
704
880
|
_forceRemove(currentNode);
|
|
705
881
|
return true;
|
|
706
882
|
}
|
|
707
883
|
|
|
708
|
-
|
|
884
|
+
/* Check whether element has a valid namespace */
|
|
885
|
+
if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
|
|
709
886
|
_forceRemove(currentNode);
|
|
710
887
|
return true;
|
|
711
888
|
}
|
|
712
889
|
|
|
713
|
-
|
|
714
|
-
if (tagName === 'svg' && currentNode.querySelectorAll('p, br, table, form, noscript').length > 0) {
|
|
890
|
+
if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
|
|
715
891
|
_forceRemove(currentNode);
|
|
716
892
|
return true;
|
|
717
893
|
}
|