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.es.js
CHANGED
|
@@ -1,39 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
return x;
|
|
3
|
-
};
|
|
1
|
+
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); } }
|
|
4
2
|
|
|
5
|
-
var
|
|
3
|
+
var hasOwnProperty = Object.hasOwnProperty;
|
|
4
|
+
var setPrototypeOf = Object.setPrototypeOf;
|
|
5
|
+
var isFrozen = Object.isFrozen;
|
|
6
|
+
var objectKeys = Object.keys;
|
|
7
|
+
var freeze = Object.freeze;
|
|
8
|
+
var seal = Object.seal; // eslint-disable-line import/no-mutable-exports
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
var
|
|
10
|
+
var _ref = typeof Reflect !== 'undefined' && Reflect;
|
|
11
|
+
var apply = _ref.apply;
|
|
12
|
+
var construct = _ref.construct;
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
if (!apply) {
|
|
15
|
+
apply = function apply(fun, thisValue, args) {
|
|
16
|
+
return fun.apply(thisValue, args);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
11
19
|
|
|
12
|
-
|
|
20
|
+
if (!freeze) {
|
|
21
|
+
freeze = function freeze(x) {
|
|
22
|
+
return x;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
13
25
|
|
|
14
|
-
|
|
26
|
+
if (!seal) {
|
|
27
|
+
seal = function seal(x) {
|
|
28
|
+
return x;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
15
31
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
32
|
+
if (!construct) {
|
|
33
|
+
construct = function construct(Func, args) {
|
|
34
|
+
return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray$1(args))))();
|
|
35
|
+
};
|
|
36
|
+
}
|
|
19
37
|
|
|
20
|
-
var
|
|
38
|
+
var arrayForEach = unapply(Array.prototype.forEach);
|
|
39
|
+
var arrayIndexOf = unapply(Array.prototype.indexOf);
|
|
40
|
+
var arrayJoin = unapply(Array.prototype.join);
|
|
41
|
+
var arrayPop = unapply(Array.prototype.pop);
|
|
42
|
+
var arrayPush = unapply(Array.prototype.push);
|
|
43
|
+
var arraySlice = unapply(Array.prototype.slice);
|
|
21
44
|
|
|
22
|
-
var
|
|
45
|
+
var stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
46
|
+
var stringMatch = unapply(String.prototype.match);
|
|
47
|
+
var stringReplace = unapply(String.prototype.replace);
|
|
48
|
+
var stringIndexOf = unapply(String.prototype.indexOf);
|
|
49
|
+
var stringTrim = unapply(String.prototype.trim);
|
|
23
50
|
|
|
24
|
-
var
|
|
51
|
+
var regExpTest = unapply(RegExp.prototype.test);
|
|
52
|
+
var regExpCreate = unconstruct(RegExp);
|
|
25
53
|
|
|
26
|
-
var
|
|
54
|
+
var typeErrorCreate = unconstruct(TypeError);
|
|
27
55
|
|
|
28
|
-
|
|
29
|
-
|
|
56
|
+
function unapply(func) {
|
|
57
|
+
return function (thisArg) {
|
|
58
|
+
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
59
|
+
args[_key - 1] = arguments[_key];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return apply(func, thisArg, args);
|
|
63
|
+
};
|
|
64
|
+
}
|
|
30
65
|
|
|
31
|
-
|
|
32
|
-
|
|
66
|
+
function unconstruct(func) {
|
|
67
|
+
return function () {
|
|
68
|
+
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
69
|
+
args[_key2] = arguments[_key2];
|
|
70
|
+
}
|
|
33
71
|
|
|
34
|
-
|
|
35
|
-
apply$1 = function apply(fun, thisValue, args) {
|
|
36
|
-
return fun.apply(thisValue, args);
|
|
72
|
+
return construct(func, args);
|
|
37
73
|
};
|
|
38
74
|
}
|
|
39
75
|
|
|
@@ -50,10 +86,10 @@ function addToSet(set, array) {
|
|
|
50
86
|
while (l--) {
|
|
51
87
|
var element = array[l];
|
|
52
88
|
if (typeof element === 'string') {
|
|
53
|
-
var lcElement = element
|
|
89
|
+
var lcElement = stringToLowerCase(element);
|
|
54
90
|
if (lcElement !== element) {
|
|
55
91
|
// Config presets (e.g. tags.js, attrs.js) are immutable.
|
|
56
|
-
if (!
|
|
92
|
+
if (!isFrozen(array)) {
|
|
57
93
|
array[l] = lcElement;
|
|
58
94
|
}
|
|
59
95
|
|
|
@@ -73,7 +109,7 @@ function clone(object) {
|
|
|
73
109
|
|
|
74
110
|
var property = void 0;
|
|
75
111
|
for (property in object) {
|
|
76
|
-
if (apply
|
|
112
|
+
if (apply(hasOwnProperty, object, [property])) {
|
|
77
113
|
newObject[property] = object[property];
|
|
78
114
|
}
|
|
79
115
|
}
|
|
@@ -81,9 +117,24 @@ function clone(object) {
|
|
|
81
117
|
return newObject;
|
|
82
118
|
}
|
|
83
119
|
|
|
84
|
-
var
|
|
85
|
-
|
|
86
|
-
|
|
120
|
+
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']);
|
|
121
|
+
|
|
122
|
+
// SVG
|
|
123
|
+
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']);
|
|
124
|
+
|
|
125
|
+
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']);
|
|
126
|
+
|
|
127
|
+
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']);
|
|
128
|
+
|
|
129
|
+
var text = freeze(['#text']);
|
|
130
|
+
|
|
131
|
+
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']);
|
|
132
|
+
|
|
133
|
+
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']);
|
|
134
|
+
|
|
135
|
+
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']);
|
|
136
|
+
|
|
137
|
+
var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
87
138
|
|
|
88
139
|
var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
|
|
89
140
|
var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
|
|
@@ -99,22 +150,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
|
|
|
99
150
|
|
|
100
151
|
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); } }
|
|
101
152
|
|
|
102
|
-
var _ref = typeof Reflect !== 'undefined' && Reflect;
|
|
103
|
-
var apply = _ref.apply;
|
|
104
|
-
|
|
105
|
-
var arraySlice = Array.prototype.slice;
|
|
106
|
-
var freeze = Object.freeze;
|
|
107
|
-
|
|
108
153
|
var getGlobal = function getGlobal() {
|
|
109
154
|
return typeof window === 'undefined' ? null : window;
|
|
110
155
|
};
|
|
111
156
|
|
|
112
|
-
if (!apply) {
|
|
113
|
-
apply = function apply(fun, thisValue, args) {
|
|
114
|
-
return fun.apply(thisValue, args);
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
157
|
/**
|
|
119
158
|
* Creates a no-op policy for internal use only.
|
|
120
159
|
* Don't export this function outside this module!
|
|
@@ -165,7 +204,7 @@ function createDOMPurify() {
|
|
|
165
204
|
* Version label, exposed for easier checks
|
|
166
205
|
* if DOMPurify is up to date or not
|
|
167
206
|
*/
|
|
168
|
-
DOMPurify.version = '2.0.
|
|
207
|
+
DOMPurify.version = '2.0.8';
|
|
169
208
|
|
|
170
209
|
/**
|
|
171
210
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -183,7 +222,6 @@ function createDOMPurify() {
|
|
|
183
222
|
|
|
184
223
|
var originalDocument = window.document;
|
|
185
224
|
var useDOMParser = false;
|
|
186
|
-
var removeSVGAttr = false;
|
|
187
225
|
var removeTitle = false;
|
|
188
226
|
|
|
189
227
|
var document = window.document;
|
|
@@ -196,7 +234,7 @@ function createDOMPurify() {
|
|
|
196
234
|
Text = window.Text,
|
|
197
235
|
Comment = window.Comment,
|
|
198
236
|
DOMParser = window.DOMParser,
|
|
199
|
-
|
|
237
|
+
trustedTypes = window.trustedTypes;
|
|
200
238
|
|
|
201
239
|
// As per issue #47, the web-components registry is inherited by a
|
|
202
240
|
// new document created via createHTMLDocument. As per the spec
|
|
@@ -212,7 +250,7 @@ function createDOMPurify() {
|
|
|
212
250
|
}
|
|
213
251
|
}
|
|
214
252
|
|
|
215
|
-
var trustedTypesPolicy = _createTrustedTypesPolicy(
|
|
253
|
+
var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
|
|
216
254
|
var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
|
|
217
255
|
|
|
218
256
|
var _document = document,
|
|
@@ -319,7 +357,7 @@ function createDOMPurify() {
|
|
|
319
357
|
var USE_PROFILES = {};
|
|
320
358
|
|
|
321
359
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
322
|
-
var FORBID_CONTENTS = addToSet({}, ['audio', 'colgroup', 'head', 'math', 'script', 'style', 'template', 'thead', '
|
|
360
|
+
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']);
|
|
323
361
|
|
|
324
362
|
/* Tags that are safe for data: URIs */
|
|
325
363
|
var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
|
|
@@ -373,9 +411,7 @@ function createDOMPurify() {
|
|
|
373
411
|
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
|
374
412
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
375
413
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
376
|
-
|
|
377
414
|
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
378
|
-
|
|
379
415
|
if (SAFE_FOR_TEMPLATES) {
|
|
380
416
|
ALLOW_DATA_ATTR = false;
|
|
381
417
|
}
|
|
@@ -464,7 +500,7 @@ function createDOMPurify() {
|
|
|
464
500
|
* @param {Node} node a DOM node
|
|
465
501
|
*/
|
|
466
502
|
var _forceRemove = function _forceRemove(node) {
|
|
467
|
-
DOMPurify.removed
|
|
503
|
+
arrayPush(DOMPurify.removed, { element: node });
|
|
468
504
|
try {
|
|
469
505
|
node.parentNode.removeChild(node);
|
|
470
506
|
} catch (error) {
|
|
@@ -480,12 +516,12 @@ function createDOMPurify() {
|
|
|
480
516
|
*/
|
|
481
517
|
var _removeAttribute = function _removeAttribute(name, node) {
|
|
482
518
|
try {
|
|
483
|
-
DOMPurify.removed
|
|
519
|
+
arrayPush(DOMPurify.removed, {
|
|
484
520
|
attribute: node.getAttributeNode(name),
|
|
485
521
|
from: node
|
|
486
522
|
});
|
|
487
523
|
} catch (error) {
|
|
488
|
-
DOMPurify.removed
|
|
524
|
+
arrayPush(DOMPurify.removed, {
|
|
489
525
|
attribute: null,
|
|
490
526
|
from: node
|
|
491
527
|
});
|
|
@@ -509,17 +545,15 @@ function createDOMPurify() {
|
|
|
509
545
|
dirty = '<remove></remove>' + dirty;
|
|
510
546
|
} else {
|
|
511
547
|
/* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
|
|
512
|
-
var matches = dirty
|
|
548
|
+
var matches = stringMatch(dirty, /^[\s]+/);
|
|
513
549
|
leadingWhitespace = matches && matches[0];
|
|
514
|
-
if (leadingWhitespace) {
|
|
515
|
-
dirty = dirty.slice(leadingWhitespace.length);
|
|
516
|
-
}
|
|
517
550
|
}
|
|
518
551
|
|
|
552
|
+
var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
519
553
|
/* Use DOMParser to workaround Firefox bug (see comment below) */
|
|
520
554
|
if (useDOMParser) {
|
|
521
555
|
try {
|
|
522
|
-
doc = new DOMParser().parseFromString(
|
|
556
|
+
doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
|
|
523
557
|
} catch (error) {}
|
|
524
558
|
}
|
|
525
559
|
|
|
@@ -536,10 +570,10 @@ function createDOMPurify() {
|
|
|
536
570
|
body = _doc.body;
|
|
537
571
|
|
|
538
572
|
body.parentNode.removeChild(body.parentNode.firstElementChild);
|
|
539
|
-
body.outerHTML =
|
|
573
|
+
body.outerHTML = dirtyPayload;
|
|
540
574
|
}
|
|
541
575
|
|
|
542
|
-
if (leadingWhitespace) {
|
|
576
|
+
if (dirty && leadingWhitespace) {
|
|
543
577
|
doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
|
|
544
578
|
}
|
|
545
579
|
|
|
@@ -569,20 +603,11 @@ function createDOMPurify() {
|
|
|
569
603
|
(function () {
|
|
570
604
|
try {
|
|
571
605
|
var doc = _initDocument('<x/><title></title><img>');
|
|
572
|
-
if (/<\/title
|
|
606
|
+
if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
|
|
573
607
|
removeTitle = true;
|
|
574
608
|
}
|
|
575
609
|
} catch (error) {}
|
|
576
610
|
})();
|
|
577
|
-
|
|
578
|
-
(function () {
|
|
579
|
-
try {
|
|
580
|
-
var doc = _initDocument('<svg></p></svg>');
|
|
581
|
-
if (doc.querySelector('svg p')) {
|
|
582
|
-
removeSVGAttr = true;
|
|
583
|
-
}
|
|
584
|
-
} catch (error) {}
|
|
585
|
-
})();
|
|
586
611
|
}
|
|
587
612
|
|
|
588
613
|
/**
|
|
@@ -638,7 +663,7 @@ function createDOMPurify() {
|
|
|
638
663
|
return;
|
|
639
664
|
}
|
|
640
665
|
|
|
641
|
-
hooks[entryPoint]
|
|
666
|
+
arrayForEach(hooks[entryPoint], function (hook) {
|
|
642
667
|
hook.call(DOMPurify, currentNode, data, CONFIG);
|
|
643
668
|
});
|
|
644
669
|
};
|
|
@@ -667,7 +692,7 @@ function createDOMPurify() {
|
|
|
667
692
|
}
|
|
668
693
|
|
|
669
694
|
/* Now let's check the element's type and name */
|
|
670
|
-
var tagName = currentNode.nodeName
|
|
695
|
+
var tagName = stringToLowerCase(currentNode.nodeName);
|
|
671
696
|
|
|
672
697
|
/* Execute a hook if present */
|
|
673
698
|
_executeHook('uponSanitizeElement', currentNode, {
|
|
@@ -675,6 +700,12 @@ function createDOMPurify() {
|
|
|
675
700
|
allowedTags: ALLOWED_TAGS
|
|
676
701
|
});
|
|
677
702
|
|
|
703
|
+
/* Take care of an mXSS pattern using p, br inside svg, math */
|
|
704
|
+
if ((tagName === 'svg' || tagName === 'math') && currentNode.querySelectorAll('p, br').length !== 0) {
|
|
705
|
+
_forceRemove(currentNode);
|
|
706
|
+
return true;
|
|
707
|
+
}
|
|
708
|
+
|
|
678
709
|
/* Remove element if anything forbids its presence */
|
|
679
710
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
680
711
|
/* Keep content except for black-listed elements */
|
|
@@ -690,34 +721,23 @@ function createDOMPurify() {
|
|
|
690
721
|
}
|
|
691
722
|
|
|
692
723
|
/* Remove in case a noscript/noembed XSS is suspected */
|
|
693
|
-
if (tagName === 'noscript' && /<\/noscript/i
|
|
724
|
+
if (tagName === 'noscript' && regExpTest(/<\/noscript/i, currentNode.innerHTML)) {
|
|
694
725
|
_forceRemove(currentNode);
|
|
695
726
|
return true;
|
|
696
727
|
}
|
|
697
728
|
|
|
698
|
-
if (tagName === 'noembed' && /<\/noembed/i
|
|
699
|
-
_forceRemove(currentNode);
|
|
700
|
-
return true;
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
/* Remove in case an mXSS is suspected */
|
|
704
|
-
if (currentNode.namespaceURI && /svg|math/i.test(currentNode.namespaceURI) && currentNode.textContent && new RegExp('</' + tagName, 'i').test(currentNode.textContent)) {
|
|
705
|
-
_forceRemove(currentNode);
|
|
706
|
-
return true;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
if ((tagName === 'svg' || tagName === 'math') && (currentNode.querySelectorAll('template') || currentNode.querySelectorAll('svg') || currentNode.querySelectorAll('math'))) {
|
|
729
|
+
if (tagName === 'noembed' && regExpTest(/<\/noembed/i, currentNode.innerHTML)) {
|
|
710
730
|
_forceRemove(currentNode);
|
|
711
731
|
return true;
|
|
712
732
|
}
|
|
713
733
|
|
|
714
734
|
/* Convert markup to cover jQuery behavior */
|
|
715
|
-
if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g
|
|
716
|
-
DOMPurify.removed
|
|
735
|
+
if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && regExpTest(/</g, currentNode.textContent)) {
|
|
736
|
+
arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
|
|
717
737
|
if (currentNode.innerHTML) {
|
|
718
|
-
currentNode.innerHTML = currentNode.innerHTML
|
|
738
|
+
currentNode.innerHTML = stringReplace(currentNode.innerHTML, /</g, '<');
|
|
719
739
|
} else {
|
|
720
|
-
currentNode.innerHTML = currentNode.textContent
|
|
740
|
+
currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '<');
|
|
721
741
|
}
|
|
722
742
|
}
|
|
723
743
|
|
|
@@ -725,10 +745,10 @@ function createDOMPurify() {
|
|
|
725
745
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
|
726
746
|
/* Get the element's text content */
|
|
727
747
|
content = currentNode.textContent;
|
|
728
|
-
content = content
|
|
729
|
-
content = content
|
|
748
|
+
content = stringReplace(content, MUSTACHE_EXPR$$1, ' ');
|
|
749
|
+
content = stringReplace(content, ERB_EXPR$$1, ' ');
|
|
730
750
|
if (currentNode.textContent !== content) {
|
|
731
|
-
DOMPurify.removed
|
|
751
|
+
arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
|
|
732
752
|
currentNode.textContent = content;
|
|
733
753
|
}
|
|
734
754
|
}
|
|
@@ -758,9 +778,9 @@ function createDOMPurify() {
|
|
|
758
778
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
759
779
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
760
780
|
We don't need to check the value; it's always URI safe. */
|
|
761
|
-
if (ALLOW_DATA_ATTR && DATA_ATTR$$1
|
|
781
|
+
if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) {
|
|
762
782
|
// This attribute is safe
|
|
763
|
-
} else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1
|
|
783
|
+
} else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) {
|
|
764
784
|
// This attribute is safe
|
|
765
785
|
/* Otherwise, check the name is permitted */
|
|
766
786
|
} else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
@@ -771,16 +791,16 @@ function createDOMPurify() {
|
|
|
771
791
|
// This attribute is safe
|
|
772
792
|
/* Check no script, data or unknown possibly unsafe URI
|
|
773
793
|
unless we know URI values are safe for that attribute */
|
|
774
|
-
} else if (IS_ALLOWED_URI$$1
|
|
794
|
+
} else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
|
|
775
795
|
// This attribute is safe
|
|
776
796
|
/* Keep image data URIs alive if src/xlink:href is allowed */
|
|
777
797
|
/* Further prevent gadget XSS for dynamically built script tags */
|
|
778
|
-
} else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && value
|
|
798
|
+
} else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) {
|
|
779
799
|
// This attribute is safe
|
|
780
800
|
/* Allow unknown protocols: This provides support for links that
|
|
781
801
|
are handled by protocol handlers which may be unknown ahead of
|
|
782
802
|
time, e.g. fb:, spotify: */
|
|
783
|
-
} else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1
|
|
803
|
+
} else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
|
|
784
804
|
// This attribute is safe
|
|
785
805
|
/* Check for binary attributes */
|
|
786
806
|
// eslint-disable-next-line no-negated-condition
|
|
@@ -837,21 +857,19 @@ function createDOMPurify() {
|
|
|
837
857
|
name = _attr.name,
|
|
838
858
|
namespaceURI = _attr.namespaceURI;
|
|
839
859
|
|
|
840
|
-
value = attr.value
|
|
841
|
-
lcName = name
|
|
860
|
+
value = stringTrim(attr.value);
|
|
861
|
+
lcName = stringToLowerCase(name);
|
|
842
862
|
|
|
843
863
|
/* Execute a hook if present */
|
|
844
864
|
hookEvent.attrName = lcName;
|
|
845
865
|
hookEvent.attrValue = value;
|
|
846
866
|
hookEvent.keepAttr = true;
|
|
867
|
+
hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
|
|
847
868
|
_executeHook('uponSanitizeAttribute', currentNode, hookEvent);
|
|
848
869
|
value = hookEvent.attrValue;
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
if (removeSVGAttr && /<\//.test(value)) {
|
|
853
|
-
_forceRemove(currentNode);
|
|
854
|
-
}
|
|
870
|
+
/* Did the hooks approve of the attribute? */
|
|
871
|
+
if (hookEvent.forceKeepAttr) {
|
|
872
|
+
continue;
|
|
855
873
|
}
|
|
856
874
|
|
|
857
875
|
/* Remove attribute */
|
|
@@ -860,10 +878,10 @@ function createDOMPurify() {
|
|
|
860
878
|
// attribute at the time.
|
|
861
879
|
if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
|
|
862
880
|
idAttr = attributes.id;
|
|
863
|
-
attributes =
|
|
881
|
+
attributes = arraySlice(attributes, []);
|
|
864
882
|
_removeAttribute('id', currentNode);
|
|
865
883
|
_removeAttribute(name, currentNode);
|
|
866
|
-
if (attributes
|
|
884
|
+
if (arrayIndexOf(attributes, idAttr) > l) {
|
|
867
885
|
currentNode.setAttribute('id', idAttr.value);
|
|
868
886
|
}
|
|
869
887
|
} else if (
|
|
@@ -887,10 +905,22 @@ function createDOMPurify() {
|
|
|
887
905
|
continue;
|
|
888
906
|
}
|
|
889
907
|
|
|
908
|
+
/* Work around a security issue in jQuery 3.0 */
|
|
909
|
+
if (SAFE_FOR_JQUERY && regExpTest(/\/>/i, value)) {
|
|
910
|
+
_removeAttribute(name, currentNode);
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
/* Take care of an mXSS pattern using namespace switches */
|
|
915
|
+
if (regExpTest(/svg|math/i, currentNode.namespaceURI) && regExpTest(regExpCreate('</(' + arrayJoin(objectKeys(FORBID_CONTENTS), '|') + ')', 'i'), value)) {
|
|
916
|
+
_removeAttribute(name, currentNode);
|
|
917
|
+
continue;
|
|
918
|
+
}
|
|
919
|
+
|
|
890
920
|
/* Sanitize attribute content to be template-safe */
|
|
891
921
|
if (SAFE_FOR_TEMPLATES) {
|
|
892
|
-
value = value
|
|
893
|
-
value = value
|
|
922
|
+
value = stringReplace(value, MUSTACHE_EXPR$$1, ' ');
|
|
923
|
+
value = stringReplace(value, ERB_EXPR$$1, ' ');
|
|
894
924
|
}
|
|
895
925
|
|
|
896
926
|
/* Is `value` valid for this attribute? */
|
|
@@ -908,7 +938,7 @@ function createDOMPurify() {
|
|
|
908
938
|
currentNode.setAttribute(name, value);
|
|
909
939
|
}
|
|
910
940
|
|
|
911
|
-
DOMPurify.removed
|
|
941
|
+
arrayPop(DOMPurify.removed);
|
|
912
942
|
} catch (error) {}
|
|
913
943
|
}
|
|
914
944
|
|
|
@@ -975,11 +1005,11 @@ function createDOMPurify() {
|
|
|
975
1005
|
if (typeof dirty !== 'string' && !_isNode(dirty)) {
|
|
976
1006
|
// eslint-disable-next-line no-negated-condition
|
|
977
1007
|
if (typeof dirty.toString !== 'function') {
|
|
978
|
-
throw
|
|
1008
|
+
throw typeErrorCreate('toString is not a function');
|
|
979
1009
|
} else {
|
|
980
1010
|
dirty = dirty.toString();
|
|
981
1011
|
if (typeof dirty !== 'string') {
|
|
982
|
-
throw
|
|
1012
|
+
throw typeErrorCreate('dirty is not a string, aborting');
|
|
983
1013
|
}
|
|
984
1014
|
}
|
|
985
1015
|
}
|
|
@@ -1007,6 +1037,11 @@ function createDOMPurify() {
|
|
|
1007
1037
|
/* Clean up removed elements */
|
|
1008
1038
|
DOMPurify.removed = [];
|
|
1009
1039
|
|
|
1040
|
+
/* Check if dirty is correctly typed for IN_PLACE */
|
|
1041
|
+
if (typeof dirty === 'string') {
|
|
1042
|
+
IN_PLACE = false;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1010
1045
|
if (IN_PLACE) {
|
|
1011
1046
|
/* No special handling necessary for in-place sanitization */
|
|
1012
1047
|
} else if (dirty instanceof Node) {
|
|
@@ -1105,8 +1140,8 @@ function createDOMPurify() {
|
|
|
1105
1140
|
|
|
1106
1141
|
/* Sanitize final string template-safe */
|
|
1107
1142
|
if (SAFE_FOR_TEMPLATES) {
|
|
1108
|
-
serializedHTML = serializedHTML
|
|
1109
|
-
serializedHTML = serializedHTML
|
|
1143
|
+
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
|
|
1144
|
+
serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' ');
|
|
1110
1145
|
}
|
|
1111
1146
|
|
|
1112
1147
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
|
@@ -1149,8 +1184,8 @@ function createDOMPurify() {
|
|
|
1149
1184
|
_parseConfig({});
|
|
1150
1185
|
}
|
|
1151
1186
|
|
|
1152
|
-
var lcTag = tag
|
|
1153
|
-
var lcName = attr
|
|
1187
|
+
var lcTag = stringToLowerCase(tag);
|
|
1188
|
+
var lcName = stringToLowerCase(attr);
|
|
1154
1189
|
return _isValidAttribute(lcTag, lcName, value);
|
|
1155
1190
|
};
|
|
1156
1191
|
|
|
@@ -1167,7 +1202,7 @@ function createDOMPurify() {
|
|
|
1167
1202
|
}
|
|
1168
1203
|
|
|
1169
1204
|
hooks[entryPoint] = hooks[entryPoint] || [];
|
|
1170
|
-
hooks[entryPoint]
|
|
1205
|
+
arrayPush(hooks[entryPoint], hookFunction);
|
|
1171
1206
|
};
|
|
1172
1207
|
|
|
1173
1208
|
/**
|
|
@@ -1179,7 +1214,7 @@ function createDOMPurify() {
|
|
|
1179
1214
|
*/
|
|
1180
1215
|
DOMPurify.removeHook = function (entryPoint) {
|
|
1181
1216
|
if (hooks[entryPoint]) {
|
|
1182
|
-
hooks[entryPoint]
|
|
1217
|
+
arrayPop(hooks[entryPoint]);
|
|
1183
1218
|
}
|
|
1184
1219
|
};
|
|
1185
1220
|
|