dompurify 2.0.4 → 2.0.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 +26 -21
- package/dist/purify.cjs.js +151 -116
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +151 -116
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +151 -116
- 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 +4 -4
package/dist/purify.cjs.js
CHANGED
|
@@ -1,41 +1,77 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
return x;
|
|
5
|
-
};
|
|
3
|
+
function _toConsumableArray$1(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
|
6
4
|
|
|
7
|
-
var
|
|
5
|
+
var hasOwnProperty = Object.hasOwnProperty;
|
|
6
|
+
var setPrototypeOf = Object.setPrototypeOf;
|
|
7
|
+
var isFrozen = Object.isFrozen;
|
|
8
|
+
var objectKeys = Object.keys;
|
|
9
|
+
var freeze = Object.freeze;
|
|
10
|
+
var seal = Object.seal; // eslint-disable-line import/no-mutable-exports
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
var
|
|
12
|
+
var _ref = typeof Reflect !== 'undefined' && Reflect;
|
|
13
|
+
var apply = _ref.apply;
|
|
14
|
+
var construct = _ref.construct;
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
if (!apply) {
|
|
17
|
+
apply = function apply(fun, thisValue, args) {
|
|
18
|
+
return fun.apply(thisValue, args);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
13
21
|
|
|
14
|
-
|
|
22
|
+
if (!freeze) {
|
|
23
|
+
freeze = function freeze(x) {
|
|
24
|
+
return x;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
15
27
|
|
|
16
|
-
|
|
28
|
+
if (!seal) {
|
|
29
|
+
seal = function seal(x) {
|
|
30
|
+
return x;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
17
33
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
34
|
+
if (!construct) {
|
|
35
|
+
construct = function construct(Func, args) {
|
|
36
|
+
return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray$1(args))))();
|
|
37
|
+
};
|
|
38
|
+
}
|
|
21
39
|
|
|
22
|
-
var
|
|
40
|
+
var arrayForEach = unapply(Array.prototype.forEach);
|
|
41
|
+
var arrayIndexOf = unapply(Array.prototype.indexOf);
|
|
42
|
+
var arrayJoin = unapply(Array.prototype.join);
|
|
43
|
+
var arrayPop = unapply(Array.prototype.pop);
|
|
44
|
+
var arrayPush = unapply(Array.prototype.push);
|
|
45
|
+
var arraySlice = unapply(Array.prototype.slice);
|
|
23
46
|
|
|
24
|
-
var
|
|
47
|
+
var stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
48
|
+
var stringMatch = unapply(String.prototype.match);
|
|
49
|
+
var stringReplace = unapply(String.prototype.replace);
|
|
50
|
+
var stringIndexOf = unapply(String.prototype.indexOf);
|
|
51
|
+
var stringTrim = unapply(String.prototype.trim);
|
|
25
52
|
|
|
26
|
-
var
|
|
53
|
+
var regExpTest = unapply(RegExp.prototype.test);
|
|
54
|
+
var regExpCreate = unconstruct(RegExp);
|
|
27
55
|
|
|
28
|
-
var
|
|
56
|
+
var typeErrorCreate = unconstruct(TypeError);
|
|
29
57
|
|
|
30
|
-
|
|
31
|
-
|
|
58
|
+
function unapply(func) {
|
|
59
|
+
return function (thisArg) {
|
|
60
|
+
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
61
|
+
args[_key - 1] = arguments[_key];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return apply(func, thisArg, args);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
32
67
|
|
|
33
|
-
|
|
34
|
-
|
|
68
|
+
function unconstruct(func) {
|
|
69
|
+
return function () {
|
|
70
|
+
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
71
|
+
args[_key2] = arguments[_key2];
|
|
72
|
+
}
|
|
35
73
|
|
|
36
|
-
|
|
37
|
-
apply$1 = function apply(fun, thisValue, args) {
|
|
38
|
-
return fun.apply(thisValue, args);
|
|
74
|
+
return construct(func, args);
|
|
39
75
|
};
|
|
40
76
|
}
|
|
41
77
|
|
|
@@ -52,10 +88,10 @@ function addToSet(set, array) {
|
|
|
52
88
|
while (l--) {
|
|
53
89
|
var element = array[l];
|
|
54
90
|
if (typeof element === 'string') {
|
|
55
|
-
var lcElement = element
|
|
91
|
+
var lcElement = stringToLowerCase(element);
|
|
56
92
|
if (lcElement !== element) {
|
|
57
93
|
// Config presets (e.g. tags.js, attrs.js) are immutable.
|
|
58
|
-
if (!
|
|
94
|
+
if (!isFrozen(array)) {
|
|
59
95
|
array[l] = lcElement;
|
|
60
96
|
}
|
|
61
97
|
|
|
@@ -75,7 +111,7 @@ function clone(object) {
|
|
|
75
111
|
|
|
76
112
|
var property = void 0;
|
|
77
113
|
for (property in object) {
|
|
78
|
-
if (apply
|
|
114
|
+
if (apply(hasOwnProperty, object, [property])) {
|
|
79
115
|
newObject[property] = object[property];
|
|
80
116
|
}
|
|
81
117
|
}
|
|
@@ -83,9 +119,24 @@ function clone(object) {
|
|
|
83
119
|
return newObject;
|
|
84
120
|
}
|
|
85
121
|
|
|
86
|
-
var
|
|
87
|
-
|
|
88
|
-
|
|
122
|
+
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', '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']);
|
|
123
|
+
|
|
124
|
+
// SVG
|
|
125
|
+
var svg = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'audio', 'canvas', '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', 'video', 'view', 'vkern']);
|
|
126
|
+
|
|
127
|
+
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']);
|
|
128
|
+
|
|
129
|
+
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']);
|
|
130
|
+
|
|
131
|
+
var text = freeze(['#text']);
|
|
132
|
+
|
|
133
|
+
var html$1 = freeze(['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', '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', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns']);
|
|
134
|
+
|
|
135
|
+
var svg$1 = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', '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', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', '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']);
|
|
136
|
+
|
|
137
|
+
var mathMl$1 = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
|
|
138
|
+
|
|
139
|
+
var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
89
140
|
|
|
90
141
|
var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
|
|
91
142
|
var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
|
|
@@ -101,22 +152,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
|
|
|
101
152
|
|
|
102
153
|
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
|
103
154
|
|
|
104
|
-
var _ref = typeof Reflect !== 'undefined' && Reflect;
|
|
105
|
-
var apply = _ref.apply;
|
|
106
|
-
|
|
107
|
-
var arraySlice = Array.prototype.slice;
|
|
108
|
-
var freeze = Object.freeze;
|
|
109
|
-
|
|
110
155
|
var getGlobal = function getGlobal() {
|
|
111
156
|
return typeof window === 'undefined' ? null : window;
|
|
112
157
|
};
|
|
113
158
|
|
|
114
|
-
if (!apply) {
|
|
115
|
-
apply = function apply(fun, thisValue, args) {
|
|
116
|
-
return fun.apply(thisValue, args);
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
159
|
/**
|
|
121
160
|
* Creates a no-op policy for internal use only.
|
|
122
161
|
* Don't export this function outside this module!
|
|
@@ -167,7 +206,7 @@ function createDOMPurify() {
|
|
|
167
206
|
* Version label, exposed for easier checks
|
|
168
207
|
* if DOMPurify is up to date or not
|
|
169
208
|
*/
|
|
170
|
-
DOMPurify.version = '2.0.
|
|
209
|
+
DOMPurify.version = '2.0.8';
|
|
171
210
|
|
|
172
211
|
/**
|
|
173
212
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -185,7 +224,6 @@ function createDOMPurify() {
|
|
|
185
224
|
|
|
186
225
|
var originalDocument = window.document;
|
|
187
226
|
var useDOMParser = false;
|
|
188
|
-
var removeSVGAttr = false;
|
|
189
227
|
var removeTitle = false;
|
|
190
228
|
|
|
191
229
|
var document = window.document;
|
|
@@ -198,7 +236,7 @@ function createDOMPurify() {
|
|
|
198
236
|
Text = window.Text,
|
|
199
237
|
Comment = window.Comment,
|
|
200
238
|
DOMParser = window.DOMParser,
|
|
201
|
-
|
|
239
|
+
trustedTypes = window.trustedTypes;
|
|
202
240
|
|
|
203
241
|
// As per issue #47, the web-components registry is inherited by a
|
|
204
242
|
// new document created via createHTMLDocument. As per the spec
|
|
@@ -214,7 +252,7 @@ function createDOMPurify() {
|
|
|
214
252
|
}
|
|
215
253
|
}
|
|
216
254
|
|
|
217
|
-
var trustedTypesPolicy = _createTrustedTypesPolicy(
|
|
255
|
+
var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
|
|
218
256
|
var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
|
|
219
257
|
|
|
220
258
|
var _document = document,
|
|
@@ -321,7 +359,7 @@ function createDOMPurify() {
|
|
|
321
359
|
var USE_PROFILES = {};
|
|
322
360
|
|
|
323
361
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
324
|
-
var FORBID_CONTENTS = addToSet({}, ['audio', 'colgroup', 'head', 'math', 'script', 'style', 'template', 'thead', '
|
|
362
|
+
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']);
|
|
325
363
|
|
|
326
364
|
/* Tags that are safe for data: URIs */
|
|
327
365
|
var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
|
|
@@ -375,9 +413,7 @@ function createDOMPurify() {
|
|
|
375
413
|
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
|
376
414
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
377
415
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
378
|
-
|
|
379
416
|
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
380
|
-
|
|
381
417
|
if (SAFE_FOR_TEMPLATES) {
|
|
382
418
|
ALLOW_DATA_ATTR = false;
|
|
383
419
|
}
|
|
@@ -466,7 +502,7 @@ function createDOMPurify() {
|
|
|
466
502
|
* @param {Node} node a DOM node
|
|
467
503
|
*/
|
|
468
504
|
var _forceRemove = function _forceRemove(node) {
|
|
469
|
-
DOMPurify.removed
|
|
505
|
+
arrayPush(DOMPurify.removed, { element: node });
|
|
470
506
|
try {
|
|
471
507
|
node.parentNode.removeChild(node);
|
|
472
508
|
} catch (error) {
|
|
@@ -482,12 +518,12 @@ function createDOMPurify() {
|
|
|
482
518
|
*/
|
|
483
519
|
var _removeAttribute = function _removeAttribute(name, node) {
|
|
484
520
|
try {
|
|
485
|
-
DOMPurify.removed
|
|
521
|
+
arrayPush(DOMPurify.removed, {
|
|
486
522
|
attribute: node.getAttributeNode(name),
|
|
487
523
|
from: node
|
|
488
524
|
});
|
|
489
525
|
} catch (error) {
|
|
490
|
-
DOMPurify.removed
|
|
526
|
+
arrayPush(DOMPurify.removed, {
|
|
491
527
|
attribute: null,
|
|
492
528
|
from: node
|
|
493
529
|
});
|
|
@@ -511,17 +547,15 @@ function createDOMPurify() {
|
|
|
511
547
|
dirty = '<remove></remove>' + dirty;
|
|
512
548
|
} else {
|
|
513
549
|
/* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
|
|
514
|
-
var matches = dirty
|
|
550
|
+
var matches = stringMatch(dirty, /^[\s]+/);
|
|
515
551
|
leadingWhitespace = matches && matches[0];
|
|
516
|
-
if (leadingWhitespace) {
|
|
517
|
-
dirty = dirty.slice(leadingWhitespace.length);
|
|
518
|
-
}
|
|
519
552
|
}
|
|
520
553
|
|
|
554
|
+
var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
521
555
|
/* Use DOMParser to workaround Firefox bug (see comment below) */
|
|
522
556
|
if (useDOMParser) {
|
|
523
557
|
try {
|
|
524
|
-
doc = new DOMParser().parseFromString(
|
|
558
|
+
doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
|
|
525
559
|
} catch (error) {}
|
|
526
560
|
}
|
|
527
561
|
|
|
@@ -538,10 +572,10 @@ function createDOMPurify() {
|
|
|
538
572
|
body = _doc.body;
|
|
539
573
|
|
|
540
574
|
body.parentNode.removeChild(body.parentNode.firstElementChild);
|
|
541
|
-
body.outerHTML =
|
|
575
|
+
body.outerHTML = dirtyPayload;
|
|
542
576
|
}
|
|
543
577
|
|
|
544
|
-
if (leadingWhitespace) {
|
|
578
|
+
if (dirty && leadingWhitespace) {
|
|
545
579
|
doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
|
|
546
580
|
}
|
|
547
581
|
|
|
@@ -571,20 +605,11 @@ function createDOMPurify() {
|
|
|
571
605
|
(function () {
|
|
572
606
|
try {
|
|
573
607
|
var doc = _initDocument('<x/><title></title><img>');
|
|
574
|
-
if (/<\/title
|
|
608
|
+
if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
|
|
575
609
|
removeTitle = true;
|
|
576
610
|
}
|
|
577
611
|
} catch (error) {}
|
|
578
612
|
})();
|
|
579
|
-
|
|
580
|
-
(function () {
|
|
581
|
-
try {
|
|
582
|
-
var doc = _initDocument('<svg></p></svg>');
|
|
583
|
-
if (doc.querySelector('svg p')) {
|
|
584
|
-
removeSVGAttr = true;
|
|
585
|
-
}
|
|
586
|
-
} catch (error) {}
|
|
587
|
-
})();
|
|
588
613
|
}
|
|
589
614
|
|
|
590
615
|
/**
|
|
@@ -640,7 +665,7 @@ function createDOMPurify() {
|
|
|
640
665
|
return;
|
|
641
666
|
}
|
|
642
667
|
|
|
643
|
-
hooks[entryPoint]
|
|
668
|
+
arrayForEach(hooks[entryPoint], function (hook) {
|
|
644
669
|
hook.call(DOMPurify, currentNode, data, CONFIG);
|
|
645
670
|
});
|
|
646
671
|
};
|
|
@@ -669,7 +694,7 @@ function createDOMPurify() {
|
|
|
669
694
|
}
|
|
670
695
|
|
|
671
696
|
/* Now let's check the element's type and name */
|
|
672
|
-
var tagName = currentNode.nodeName
|
|
697
|
+
var tagName = stringToLowerCase(currentNode.nodeName);
|
|
673
698
|
|
|
674
699
|
/* Execute a hook if present */
|
|
675
700
|
_executeHook('uponSanitizeElement', currentNode, {
|
|
@@ -677,6 +702,12 @@ function createDOMPurify() {
|
|
|
677
702
|
allowedTags: ALLOWED_TAGS
|
|
678
703
|
});
|
|
679
704
|
|
|
705
|
+
/* Take care of an mXSS pattern using p, br inside svg, math */
|
|
706
|
+
if ((tagName === 'svg' || tagName === 'math') && currentNode.querySelectorAll('p, br').length !== 0) {
|
|
707
|
+
_forceRemove(currentNode);
|
|
708
|
+
return true;
|
|
709
|
+
}
|
|
710
|
+
|
|
680
711
|
/* Remove element if anything forbids its presence */
|
|
681
712
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
682
713
|
/* Keep content except for black-listed elements */
|
|
@@ -692,34 +723,23 @@ function createDOMPurify() {
|
|
|
692
723
|
}
|
|
693
724
|
|
|
694
725
|
/* Remove in case a noscript/noembed XSS is suspected */
|
|
695
|
-
if (tagName === 'noscript' && /<\/noscript/i
|
|
726
|
+
if (tagName === 'noscript' && regExpTest(/<\/noscript/i, currentNode.innerHTML)) {
|
|
696
727
|
_forceRemove(currentNode);
|
|
697
728
|
return true;
|
|
698
729
|
}
|
|
699
730
|
|
|
700
|
-
if (tagName === 'noembed' && /<\/noembed/i
|
|
701
|
-
_forceRemove(currentNode);
|
|
702
|
-
return true;
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
/* Remove in case an mXSS is suspected */
|
|
706
|
-
if (currentNode.namespaceURI && /svg|math/i.test(currentNode.namespaceURI) && currentNode.textContent && new RegExp('</' + tagName, 'i').test(currentNode.textContent)) {
|
|
707
|
-
_forceRemove(currentNode);
|
|
708
|
-
return true;
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
if ((tagName === 'svg' || tagName === 'math') && (currentNode.querySelectorAll('template') || currentNode.querySelectorAll('svg') || currentNode.querySelectorAll('math'))) {
|
|
731
|
+
if (tagName === 'noembed' && regExpTest(/<\/noembed/i, currentNode.innerHTML)) {
|
|
712
732
|
_forceRemove(currentNode);
|
|
713
733
|
return true;
|
|
714
734
|
}
|
|
715
735
|
|
|
716
736
|
/* Convert markup to cover jQuery behavior */
|
|
717
|
-
if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g
|
|
718
|
-
DOMPurify.removed
|
|
737
|
+
if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && regExpTest(/</g, currentNode.textContent)) {
|
|
738
|
+
arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
|
|
719
739
|
if (currentNode.innerHTML) {
|
|
720
|
-
currentNode.innerHTML = currentNode.innerHTML
|
|
740
|
+
currentNode.innerHTML = stringReplace(currentNode.innerHTML, /</g, '<');
|
|
721
741
|
} else {
|
|
722
|
-
currentNode.innerHTML = currentNode.textContent
|
|
742
|
+
currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '<');
|
|
723
743
|
}
|
|
724
744
|
}
|
|
725
745
|
|
|
@@ -727,10 +747,10 @@ function createDOMPurify() {
|
|
|
727
747
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
|
728
748
|
/* Get the element's text content */
|
|
729
749
|
content = currentNode.textContent;
|
|
730
|
-
content = content
|
|
731
|
-
content = content
|
|
750
|
+
content = stringReplace(content, MUSTACHE_EXPR$$1, ' ');
|
|
751
|
+
content = stringReplace(content, ERB_EXPR$$1, ' ');
|
|
732
752
|
if (currentNode.textContent !== content) {
|
|
733
|
-
DOMPurify.removed
|
|
753
|
+
arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
|
|
734
754
|
currentNode.textContent = content;
|
|
735
755
|
}
|
|
736
756
|
}
|
|
@@ -760,9 +780,9 @@ function createDOMPurify() {
|
|
|
760
780
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
761
781
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
762
782
|
We don't need to check the value; it's always URI safe. */
|
|
763
|
-
if (ALLOW_DATA_ATTR && DATA_ATTR$$1
|
|
783
|
+
if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) {
|
|
764
784
|
// This attribute is safe
|
|
765
|
-
} else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1
|
|
785
|
+
} else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) {
|
|
766
786
|
// This attribute is safe
|
|
767
787
|
/* Otherwise, check the name is permitted */
|
|
768
788
|
} else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
@@ -773,16 +793,16 @@ function createDOMPurify() {
|
|
|
773
793
|
// This attribute is safe
|
|
774
794
|
/* Check no script, data or unknown possibly unsafe URI
|
|
775
795
|
unless we know URI values are safe for that attribute */
|
|
776
|
-
} else if (IS_ALLOWED_URI$$1
|
|
796
|
+
} else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
|
|
777
797
|
// This attribute is safe
|
|
778
798
|
/* Keep image data URIs alive if src/xlink:href is allowed */
|
|
779
799
|
/* Further prevent gadget XSS for dynamically built script tags */
|
|
780
|
-
} else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && value
|
|
800
|
+
} else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) {
|
|
781
801
|
// This attribute is safe
|
|
782
802
|
/* Allow unknown protocols: This provides support for links that
|
|
783
803
|
are handled by protocol handlers which may be unknown ahead of
|
|
784
804
|
time, e.g. fb:, spotify: */
|
|
785
|
-
} else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1
|
|
805
|
+
} else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
|
|
786
806
|
// This attribute is safe
|
|
787
807
|
/* Check for binary attributes */
|
|
788
808
|
// eslint-disable-next-line no-negated-condition
|
|
@@ -839,21 +859,19 @@ function createDOMPurify() {
|
|
|
839
859
|
name = _attr.name,
|
|
840
860
|
namespaceURI = _attr.namespaceURI;
|
|
841
861
|
|
|
842
|
-
value = attr.value
|
|
843
|
-
lcName = name
|
|
862
|
+
value = stringTrim(attr.value);
|
|
863
|
+
lcName = stringToLowerCase(name);
|
|
844
864
|
|
|
845
865
|
/* Execute a hook if present */
|
|
846
866
|
hookEvent.attrName = lcName;
|
|
847
867
|
hookEvent.attrValue = value;
|
|
848
868
|
hookEvent.keepAttr = true;
|
|
869
|
+
hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
|
|
849
870
|
_executeHook('uponSanitizeAttribute', currentNode, hookEvent);
|
|
850
871
|
value = hookEvent.attrValue;
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
if (removeSVGAttr && /<\//.test(value)) {
|
|
855
|
-
_forceRemove(currentNode);
|
|
856
|
-
}
|
|
872
|
+
/* Did the hooks approve of the attribute? */
|
|
873
|
+
if (hookEvent.forceKeepAttr) {
|
|
874
|
+
continue;
|
|
857
875
|
}
|
|
858
876
|
|
|
859
877
|
/* Remove attribute */
|
|
@@ -862,10 +880,10 @@ function createDOMPurify() {
|
|
|
862
880
|
// attribute at the time.
|
|
863
881
|
if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
|
|
864
882
|
idAttr = attributes.id;
|
|
865
|
-
attributes =
|
|
883
|
+
attributes = arraySlice(attributes, []);
|
|
866
884
|
_removeAttribute('id', currentNode);
|
|
867
885
|
_removeAttribute(name, currentNode);
|
|
868
|
-
if (attributes
|
|
886
|
+
if (arrayIndexOf(attributes, idAttr) > l) {
|
|
869
887
|
currentNode.setAttribute('id', idAttr.value);
|
|
870
888
|
}
|
|
871
889
|
} else if (
|
|
@@ -889,10 +907,22 @@ function createDOMPurify() {
|
|
|
889
907
|
continue;
|
|
890
908
|
}
|
|
891
909
|
|
|
910
|
+
/* Work around a security issue in jQuery 3.0 */
|
|
911
|
+
if (SAFE_FOR_JQUERY && regExpTest(/\/>/i, value)) {
|
|
912
|
+
_removeAttribute(name, currentNode);
|
|
913
|
+
continue;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/* Take care of an mXSS pattern using namespace switches */
|
|
917
|
+
if (regExpTest(/svg|math/i, currentNode.namespaceURI) && regExpTest(regExpCreate('</(' + arrayJoin(objectKeys(FORBID_CONTENTS), '|') + ')', 'i'), value)) {
|
|
918
|
+
_removeAttribute(name, currentNode);
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
921
|
+
|
|
892
922
|
/* Sanitize attribute content to be template-safe */
|
|
893
923
|
if (SAFE_FOR_TEMPLATES) {
|
|
894
|
-
value = value
|
|
895
|
-
value = value
|
|
924
|
+
value = stringReplace(value, MUSTACHE_EXPR$$1, ' ');
|
|
925
|
+
value = stringReplace(value, ERB_EXPR$$1, ' ');
|
|
896
926
|
}
|
|
897
927
|
|
|
898
928
|
/* Is `value` valid for this attribute? */
|
|
@@ -910,7 +940,7 @@ function createDOMPurify() {
|
|
|
910
940
|
currentNode.setAttribute(name, value);
|
|
911
941
|
}
|
|
912
942
|
|
|
913
|
-
DOMPurify.removed
|
|
943
|
+
arrayPop(DOMPurify.removed);
|
|
914
944
|
} catch (error) {}
|
|
915
945
|
}
|
|
916
946
|
|
|
@@ -977,11 +1007,11 @@ function createDOMPurify() {
|
|
|
977
1007
|
if (typeof dirty !== 'string' && !_isNode(dirty)) {
|
|
978
1008
|
// eslint-disable-next-line no-negated-condition
|
|
979
1009
|
if (typeof dirty.toString !== 'function') {
|
|
980
|
-
throw
|
|
1010
|
+
throw typeErrorCreate('toString is not a function');
|
|
981
1011
|
} else {
|
|
982
1012
|
dirty = dirty.toString();
|
|
983
1013
|
if (typeof dirty !== 'string') {
|
|
984
|
-
throw
|
|
1014
|
+
throw typeErrorCreate('dirty is not a string, aborting');
|
|
985
1015
|
}
|
|
986
1016
|
}
|
|
987
1017
|
}
|
|
@@ -1009,6 +1039,11 @@ function createDOMPurify() {
|
|
|
1009
1039
|
/* Clean up removed elements */
|
|
1010
1040
|
DOMPurify.removed = [];
|
|
1011
1041
|
|
|
1042
|
+
/* Check if dirty is correctly typed for IN_PLACE */
|
|
1043
|
+
if (typeof dirty === 'string') {
|
|
1044
|
+
IN_PLACE = false;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1012
1047
|
if (IN_PLACE) {
|
|
1013
1048
|
/* No special handling necessary for in-place sanitization */
|
|
1014
1049
|
} else if (dirty instanceof Node) {
|
|
@@ -1107,8 +1142,8 @@ function createDOMPurify() {
|
|
|
1107
1142
|
|
|
1108
1143
|
/* Sanitize final string template-safe */
|
|
1109
1144
|
if (SAFE_FOR_TEMPLATES) {
|
|
1110
|
-
serializedHTML = serializedHTML
|
|
1111
|
-
serializedHTML = serializedHTML
|
|
1145
|
+
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
|
|
1146
|
+
serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' ');
|
|
1112
1147
|
}
|
|
1113
1148
|
|
|
1114
1149
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
|
@@ -1151,8 +1186,8 @@ function createDOMPurify() {
|
|
|
1151
1186
|
_parseConfig({});
|
|
1152
1187
|
}
|
|
1153
1188
|
|
|
1154
|
-
var lcTag = tag
|
|
1155
|
-
var lcName = attr
|
|
1189
|
+
var lcTag = stringToLowerCase(tag);
|
|
1190
|
+
var lcName = stringToLowerCase(attr);
|
|
1156
1191
|
return _isValidAttribute(lcTag, lcName, value);
|
|
1157
1192
|
};
|
|
1158
1193
|
|
|
@@ -1169,7 +1204,7 @@ function createDOMPurify() {
|
|
|
1169
1204
|
}
|
|
1170
1205
|
|
|
1171
1206
|
hooks[entryPoint] = hooks[entryPoint] || [];
|
|
1172
|
-
hooks[entryPoint]
|
|
1207
|
+
arrayPush(hooks[entryPoint], hookFunction);
|
|
1173
1208
|
};
|
|
1174
1209
|
|
|
1175
1210
|
/**
|
|
@@ -1181,7 +1216,7 @@ function createDOMPurify() {
|
|
|
1181
1216
|
*/
|
|
1182
1217
|
DOMPurify.removeHook = function (entryPoint) {
|
|
1183
1218
|
if (hooks[entryPoint]) {
|
|
1184
|
-
hooks[entryPoint]
|
|
1219
|
+
arrayPop(hooks[entryPoint]);
|
|
1185
1220
|
}
|
|
1186
1221
|
};
|
|
1187
1222
|
|