dompurify 2.0.7 → 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 +21 -12
- package/dist/purify.cjs.js +139 -88
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +139 -88
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +139 -88
- 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.js
CHANGED
|
@@ -4,42 +4,78 @@
|
|
|
4
4
|
(global.DOMPurify = factory());
|
|
5
5
|
}(this, (function () { 'use strict';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
return x;
|
|
9
|
-
};
|
|
7
|
+
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); } }
|
|
10
8
|
|
|
11
|
-
var
|
|
9
|
+
var hasOwnProperty = Object.hasOwnProperty;
|
|
10
|
+
var setPrototypeOf = Object.setPrototypeOf;
|
|
11
|
+
var isFrozen = Object.isFrozen;
|
|
12
|
+
var objectKeys = Object.keys;
|
|
13
|
+
var freeze = Object.freeze;
|
|
14
|
+
var seal = Object.seal; // eslint-disable-line import/no-mutable-exports
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
var
|
|
16
|
+
var _ref = typeof Reflect !== 'undefined' && Reflect;
|
|
17
|
+
var apply = _ref.apply;
|
|
18
|
+
var construct = _ref.construct;
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
if (!apply) {
|
|
21
|
+
apply = function apply(fun, thisValue, args) {
|
|
22
|
+
return fun.apply(thisValue, args);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!freeze) {
|
|
27
|
+
freeze = function freeze(x) {
|
|
28
|
+
return x;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
17
31
|
|
|
18
|
-
|
|
32
|
+
if (!seal) {
|
|
33
|
+
seal = function seal(x) {
|
|
34
|
+
return x;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
19
37
|
|
|
20
|
-
|
|
38
|
+
if (!construct) {
|
|
39
|
+
construct = function construct(Func, args) {
|
|
40
|
+
return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray$1(args))))();
|
|
41
|
+
};
|
|
42
|
+
}
|
|
21
43
|
|
|
22
|
-
var
|
|
23
|
-
|
|
24
|
-
|
|
44
|
+
var arrayForEach = unapply(Array.prototype.forEach);
|
|
45
|
+
var arrayIndexOf = unapply(Array.prototype.indexOf);
|
|
46
|
+
var arrayJoin = unapply(Array.prototype.join);
|
|
47
|
+
var arrayPop = unapply(Array.prototype.pop);
|
|
48
|
+
var arrayPush = unapply(Array.prototype.push);
|
|
49
|
+
var arraySlice = unapply(Array.prototype.slice);
|
|
25
50
|
|
|
26
|
-
var
|
|
51
|
+
var stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
52
|
+
var stringMatch = unapply(String.prototype.match);
|
|
53
|
+
var stringReplace = unapply(String.prototype.replace);
|
|
54
|
+
var stringIndexOf = unapply(String.prototype.indexOf);
|
|
55
|
+
var stringTrim = unapply(String.prototype.trim);
|
|
27
56
|
|
|
28
|
-
var
|
|
57
|
+
var regExpTest = unapply(RegExp.prototype.test);
|
|
58
|
+
var regExpCreate = unconstruct(RegExp);
|
|
29
59
|
|
|
30
|
-
var
|
|
60
|
+
var typeErrorCreate = unconstruct(TypeError);
|
|
31
61
|
|
|
32
|
-
|
|
62
|
+
function unapply(func) {
|
|
63
|
+
return function (thisArg) {
|
|
64
|
+
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
65
|
+
args[_key - 1] = arguments[_key];
|
|
66
|
+
}
|
|
33
67
|
|
|
34
|
-
|
|
35
|
-
|
|
68
|
+
return apply(func, thisArg, args);
|
|
69
|
+
};
|
|
70
|
+
}
|
|
36
71
|
|
|
37
|
-
|
|
38
|
-
|
|
72
|
+
function unconstruct(func) {
|
|
73
|
+
return function () {
|
|
74
|
+
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
75
|
+
args[_key2] = arguments[_key2];
|
|
76
|
+
}
|
|
39
77
|
|
|
40
|
-
|
|
41
|
-
apply$1 = function apply(fun, thisValue, args) {
|
|
42
|
-
return fun.apply(thisValue, args);
|
|
78
|
+
return construct(func, args);
|
|
43
79
|
};
|
|
44
80
|
}
|
|
45
81
|
|
|
@@ -56,10 +92,10 @@ function addToSet(set, array) {
|
|
|
56
92
|
while (l--) {
|
|
57
93
|
var element = array[l];
|
|
58
94
|
if (typeof element === 'string') {
|
|
59
|
-
var lcElement = element
|
|
95
|
+
var lcElement = stringToLowerCase(element);
|
|
60
96
|
if (lcElement !== element) {
|
|
61
97
|
// Config presets (e.g. tags.js, attrs.js) are immutable.
|
|
62
|
-
if (!
|
|
98
|
+
if (!isFrozen(array)) {
|
|
63
99
|
array[l] = lcElement;
|
|
64
100
|
}
|
|
65
101
|
|
|
@@ -79,7 +115,7 @@ function clone(object) {
|
|
|
79
115
|
|
|
80
116
|
var property = void 0;
|
|
81
117
|
for (property in object) {
|
|
82
|
-
if (apply
|
|
118
|
+
if (apply(hasOwnProperty, object, [property])) {
|
|
83
119
|
newObject[property] = object[property];
|
|
84
120
|
}
|
|
85
121
|
}
|
|
@@ -87,9 +123,24 @@ function clone(object) {
|
|
|
87
123
|
return newObject;
|
|
88
124
|
}
|
|
89
125
|
|
|
90
|
-
var
|
|
91
|
-
|
|
92
|
-
|
|
126
|
+
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']);
|
|
127
|
+
|
|
128
|
+
// SVG
|
|
129
|
+
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']);
|
|
130
|
+
|
|
131
|
+
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']);
|
|
132
|
+
|
|
133
|
+
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']);
|
|
134
|
+
|
|
135
|
+
var text = freeze(['#text']);
|
|
136
|
+
|
|
137
|
+
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']);
|
|
138
|
+
|
|
139
|
+
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']);
|
|
140
|
+
|
|
141
|
+
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']);
|
|
142
|
+
|
|
143
|
+
var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
93
144
|
|
|
94
145
|
var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
|
|
95
146
|
var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
|
|
@@ -105,22 +156,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
|
|
|
105
156
|
|
|
106
157
|
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); } }
|
|
107
158
|
|
|
108
|
-
var _ref = typeof Reflect !== 'undefined' && Reflect;
|
|
109
|
-
var apply = _ref.apply;
|
|
110
|
-
|
|
111
|
-
var arraySlice = Array.prototype.slice;
|
|
112
|
-
var freeze = Object.freeze;
|
|
113
|
-
|
|
114
159
|
var getGlobal = function getGlobal() {
|
|
115
160
|
return typeof window === 'undefined' ? null : window;
|
|
116
161
|
};
|
|
117
162
|
|
|
118
|
-
if (!apply) {
|
|
119
|
-
apply = function apply(fun, thisValue, args) {
|
|
120
|
-
return fun.apply(thisValue, args);
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
163
|
/**
|
|
125
164
|
* Creates a no-op policy for internal use only.
|
|
126
165
|
* Don't export this function outside this module!
|
|
@@ -171,7 +210,7 @@ function createDOMPurify() {
|
|
|
171
210
|
* Version label, exposed for easier checks
|
|
172
211
|
* if DOMPurify is up to date or not
|
|
173
212
|
*/
|
|
174
|
-
DOMPurify.version = '2.0.
|
|
213
|
+
DOMPurify.version = '2.0.8';
|
|
175
214
|
|
|
176
215
|
/**
|
|
177
216
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -201,7 +240,7 @@ function createDOMPurify() {
|
|
|
201
240
|
Text = window.Text,
|
|
202
241
|
Comment = window.Comment,
|
|
203
242
|
DOMParser = window.DOMParser,
|
|
204
|
-
|
|
243
|
+
trustedTypes = window.trustedTypes;
|
|
205
244
|
|
|
206
245
|
// As per issue #47, the web-components registry is inherited by a
|
|
207
246
|
// new document created via createHTMLDocument. As per the spec
|
|
@@ -217,7 +256,7 @@ function createDOMPurify() {
|
|
|
217
256
|
}
|
|
218
257
|
}
|
|
219
258
|
|
|
220
|
-
var trustedTypesPolicy = _createTrustedTypesPolicy(
|
|
259
|
+
var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
|
|
221
260
|
var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
|
|
222
261
|
|
|
223
262
|
var _document = document,
|
|
@@ -378,9 +417,7 @@ function createDOMPurify() {
|
|
|
378
417
|
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
|
379
418
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
380
419
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
381
|
-
|
|
382
420
|
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
383
|
-
|
|
384
421
|
if (SAFE_FOR_TEMPLATES) {
|
|
385
422
|
ALLOW_DATA_ATTR = false;
|
|
386
423
|
}
|
|
@@ -469,7 +506,7 @@ function createDOMPurify() {
|
|
|
469
506
|
* @param {Node} node a DOM node
|
|
470
507
|
*/
|
|
471
508
|
var _forceRemove = function _forceRemove(node) {
|
|
472
|
-
DOMPurify.removed
|
|
509
|
+
arrayPush(DOMPurify.removed, { element: node });
|
|
473
510
|
try {
|
|
474
511
|
node.parentNode.removeChild(node);
|
|
475
512
|
} catch (error) {
|
|
@@ -485,12 +522,12 @@ function createDOMPurify() {
|
|
|
485
522
|
*/
|
|
486
523
|
var _removeAttribute = function _removeAttribute(name, node) {
|
|
487
524
|
try {
|
|
488
|
-
DOMPurify.removed
|
|
525
|
+
arrayPush(DOMPurify.removed, {
|
|
489
526
|
attribute: node.getAttributeNode(name),
|
|
490
527
|
from: node
|
|
491
528
|
});
|
|
492
529
|
} catch (error) {
|
|
493
|
-
DOMPurify.removed
|
|
530
|
+
arrayPush(DOMPurify.removed, {
|
|
494
531
|
attribute: null,
|
|
495
532
|
from: node
|
|
496
533
|
});
|
|
@@ -514,17 +551,15 @@ function createDOMPurify() {
|
|
|
514
551
|
dirty = '<remove></remove>' + dirty;
|
|
515
552
|
} else {
|
|
516
553
|
/* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
|
|
517
|
-
var matches = dirty
|
|
554
|
+
var matches = stringMatch(dirty, /^[\s]+/);
|
|
518
555
|
leadingWhitespace = matches && matches[0];
|
|
519
|
-
if (leadingWhitespace) {
|
|
520
|
-
dirty = dirty.slice(leadingWhitespace.length);
|
|
521
|
-
}
|
|
522
556
|
}
|
|
523
557
|
|
|
558
|
+
var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
524
559
|
/* Use DOMParser to workaround Firefox bug (see comment below) */
|
|
525
560
|
if (useDOMParser) {
|
|
526
561
|
try {
|
|
527
|
-
doc = new DOMParser().parseFromString(
|
|
562
|
+
doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
|
|
528
563
|
} catch (error) {}
|
|
529
564
|
}
|
|
530
565
|
|
|
@@ -541,7 +576,7 @@ function createDOMPurify() {
|
|
|
541
576
|
body = _doc.body;
|
|
542
577
|
|
|
543
578
|
body.parentNode.removeChild(body.parentNode.firstElementChild);
|
|
544
|
-
body.outerHTML =
|
|
579
|
+
body.outerHTML = dirtyPayload;
|
|
545
580
|
}
|
|
546
581
|
|
|
547
582
|
if (dirty && leadingWhitespace) {
|
|
@@ -574,7 +609,7 @@ function createDOMPurify() {
|
|
|
574
609
|
(function () {
|
|
575
610
|
try {
|
|
576
611
|
var doc = _initDocument('<x/><title></title><img>');
|
|
577
|
-
if (/<\/title
|
|
612
|
+
if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
|
|
578
613
|
removeTitle = true;
|
|
579
614
|
}
|
|
580
615
|
} catch (error) {}
|
|
@@ -634,7 +669,7 @@ function createDOMPurify() {
|
|
|
634
669
|
return;
|
|
635
670
|
}
|
|
636
671
|
|
|
637
|
-
hooks[entryPoint]
|
|
672
|
+
arrayForEach(hooks[entryPoint], function (hook) {
|
|
638
673
|
hook.call(DOMPurify, currentNode, data, CONFIG);
|
|
639
674
|
});
|
|
640
675
|
};
|
|
@@ -663,7 +698,7 @@ function createDOMPurify() {
|
|
|
663
698
|
}
|
|
664
699
|
|
|
665
700
|
/* Now let's check the element's type and name */
|
|
666
|
-
var tagName = currentNode.nodeName
|
|
701
|
+
var tagName = stringToLowerCase(currentNode.nodeName);
|
|
667
702
|
|
|
668
703
|
/* Execute a hook if present */
|
|
669
704
|
_executeHook('uponSanitizeElement', currentNode, {
|
|
@@ -692,23 +727,23 @@ function createDOMPurify() {
|
|
|
692
727
|
}
|
|
693
728
|
|
|
694
729
|
/* Remove in case a noscript/noembed XSS is suspected */
|
|
695
|
-
if (tagName === 'noscript' && /<\/noscript/i
|
|
730
|
+
if (tagName === 'noscript' && regExpTest(/<\/noscript/i, currentNode.innerHTML)) {
|
|
696
731
|
_forceRemove(currentNode);
|
|
697
732
|
return true;
|
|
698
733
|
}
|
|
699
734
|
|
|
700
|
-
if (tagName === 'noembed' && /<\/noembed/i
|
|
735
|
+
if (tagName === 'noembed' && regExpTest(/<\/noembed/i, currentNode.innerHTML)) {
|
|
701
736
|
_forceRemove(currentNode);
|
|
702
737
|
return true;
|
|
703
738
|
}
|
|
704
739
|
|
|
705
740
|
/* Convert markup to cover jQuery behavior */
|
|
706
|
-
if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g
|
|
707
|
-
DOMPurify.removed
|
|
741
|
+
if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && regExpTest(/</g, currentNode.textContent)) {
|
|
742
|
+
arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
|
|
708
743
|
if (currentNode.innerHTML) {
|
|
709
|
-
currentNode.innerHTML = currentNode.innerHTML
|
|
744
|
+
currentNode.innerHTML = stringReplace(currentNode.innerHTML, /</g, '<');
|
|
710
745
|
} else {
|
|
711
|
-
currentNode.innerHTML = currentNode.textContent
|
|
746
|
+
currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '<');
|
|
712
747
|
}
|
|
713
748
|
}
|
|
714
749
|
|
|
@@ -716,10 +751,10 @@ function createDOMPurify() {
|
|
|
716
751
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
|
717
752
|
/* Get the element's text content */
|
|
718
753
|
content = currentNode.textContent;
|
|
719
|
-
content = content
|
|
720
|
-
content = content
|
|
754
|
+
content = stringReplace(content, MUSTACHE_EXPR$$1, ' ');
|
|
755
|
+
content = stringReplace(content, ERB_EXPR$$1, ' ');
|
|
721
756
|
if (currentNode.textContent !== content) {
|
|
722
|
-
DOMPurify.removed
|
|
757
|
+
arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
|
|
723
758
|
currentNode.textContent = content;
|
|
724
759
|
}
|
|
725
760
|
}
|
|
@@ -749,9 +784,9 @@ function createDOMPurify() {
|
|
|
749
784
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
750
785
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
751
786
|
We don't need to check the value; it's always URI safe. */
|
|
752
|
-
if (ALLOW_DATA_ATTR && DATA_ATTR$$1
|
|
787
|
+
if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) {
|
|
753
788
|
// This attribute is safe
|
|
754
|
-
} else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1
|
|
789
|
+
} else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) {
|
|
755
790
|
// This attribute is safe
|
|
756
791
|
/* Otherwise, check the name is permitted */
|
|
757
792
|
} else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
@@ -762,16 +797,16 @@ function createDOMPurify() {
|
|
|
762
797
|
// This attribute is safe
|
|
763
798
|
/* Check no script, data or unknown possibly unsafe URI
|
|
764
799
|
unless we know URI values are safe for that attribute */
|
|
765
|
-
} else if (IS_ALLOWED_URI$$1
|
|
800
|
+
} else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
|
|
766
801
|
// This attribute is safe
|
|
767
802
|
/* Keep image data URIs alive if src/xlink:href is allowed */
|
|
768
803
|
/* Further prevent gadget XSS for dynamically built script tags */
|
|
769
|
-
} else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && value
|
|
804
|
+
} else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) {
|
|
770
805
|
// This attribute is safe
|
|
771
806
|
/* Allow unknown protocols: This provides support for links that
|
|
772
807
|
are handled by protocol handlers which may be unknown ahead of
|
|
773
808
|
time, e.g. fb:, spotify: */
|
|
774
|
-
} else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1
|
|
809
|
+
} else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
|
|
775
810
|
// This attribute is safe
|
|
776
811
|
/* Check for binary attributes */
|
|
777
812
|
// eslint-disable-next-line no-negated-condition
|
|
@@ -828,15 +863,20 @@ function createDOMPurify() {
|
|
|
828
863
|
name = _attr.name,
|
|
829
864
|
namespaceURI = _attr.namespaceURI;
|
|
830
865
|
|
|
831
|
-
value = attr.value
|
|
832
|
-
lcName = name
|
|
866
|
+
value = stringTrim(attr.value);
|
|
867
|
+
lcName = stringToLowerCase(name);
|
|
833
868
|
|
|
834
869
|
/* Execute a hook if present */
|
|
835
870
|
hookEvent.attrName = lcName;
|
|
836
871
|
hookEvent.attrValue = value;
|
|
837
872
|
hookEvent.keepAttr = true;
|
|
873
|
+
hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
|
|
838
874
|
_executeHook('uponSanitizeAttribute', currentNode, hookEvent);
|
|
839
875
|
value = hookEvent.attrValue;
|
|
876
|
+
/* Did the hooks approve of the attribute? */
|
|
877
|
+
if (hookEvent.forceKeepAttr) {
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
840
880
|
|
|
841
881
|
/* Remove attribute */
|
|
842
882
|
// Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
|
|
@@ -844,10 +884,10 @@ function createDOMPurify() {
|
|
|
844
884
|
// attribute at the time.
|
|
845
885
|
if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
|
|
846
886
|
idAttr = attributes.id;
|
|
847
|
-
attributes =
|
|
887
|
+
attributes = arraySlice(attributes, []);
|
|
848
888
|
_removeAttribute('id', currentNode);
|
|
849
889
|
_removeAttribute(name, currentNode);
|
|
850
|
-
if (attributes
|
|
890
|
+
if (arrayIndexOf(attributes, idAttr) > l) {
|
|
851
891
|
currentNode.setAttribute('id', idAttr.value);
|
|
852
892
|
}
|
|
853
893
|
} else if (
|
|
@@ -871,16 +911,22 @@ function createDOMPurify() {
|
|
|
871
911
|
continue;
|
|
872
912
|
}
|
|
873
913
|
|
|
914
|
+
/* Work around a security issue in jQuery 3.0 */
|
|
915
|
+
if (SAFE_FOR_JQUERY && regExpTest(/\/>/i, value)) {
|
|
916
|
+
_removeAttribute(name, currentNode);
|
|
917
|
+
continue;
|
|
918
|
+
}
|
|
919
|
+
|
|
874
920
|
/* Take care of an mXSS pattern using namespace switches */
|
|
875
|
-
if (/svg|math/i
|
|
921
|
+
if (regExpTest(/svg|math/i, currentNode.namespaceURI) && regExpTest(regExpCreate('</(' + arrayJoin(objectKeys(FORBID_CONTENTS), '|') + ')', 'i'), value)) {
|
|
876
922
|
_removeAttribute(name, currentNode);
|
|
877
923
|
continue;
|
|
878
924
|
}
|
|
879
925
|
|
|
880
926
|
/* Sanitize attribute content to be template-safe */
|
|
881
927
|
if (SAFE_FOR_TEMPLATES) {
|
|
882
|
-
value = value
|
|
883
|
-
value = value
|
|
928
|
+
value = stringReplace(value, MUSTACHE_EXPR$$1, ' ');
|
|
929
|
+
value = stringReplace(value, ERB_EXPR$$1, ' ');
|
|
884
930
|
}
|
|
885
931
|
|
|
886
932
|
/* Is `value` valid for this attribute? */
|
|
@@ -898,7 +944,7 @@ function createDOMPurify() {
|
|
|
898
944
|
currentNode.setAttribute(name, value);
|
|
899
945
|
}
|
|
900
946
|
|
|
901
|
-
DOMPurify.removed
|
|
947
|
+
arrayPop(DOMPurify.removed);
|
|
902
948
|
} catch (error) {}
|
|
903
949
|
}
|
|
904
950
|
|
|
@@ -965,11 +1011,11 @@ function createDOMPurify() {
|
|
|
965
1011
|
if (typeof dirty !== 'string' && !_isNode(dirty)) {
|
|
966
1012
|
// eslint-disable-next-line no-negated-condition
|
|
967
1013
|
if (typeof dirty.toString !== 'function') {
|
|
968
|
-
throw
|
|
1014
|
+
throw typeErrorCreate('toString is not a function');
|
|
969
1015
|
} else {
|
|
970
1016
|
dirty = dirty.toString();
|
|
971
1017
|
if (typeof dirty !== 'string') {
|
|
972
|
-
throw
|
|
1018
|
+
throw typeErrorCreate('dirty is not a string, aborting');
|
|
973
1019
|
}
|
|
974
1020
|
}
|
|
975
1021
|
}
|
|
@@ -997,6 +1043,11 @@ function createDOMPurify() {
|
|
|
997
1043
|
/* Clean up removed elements */
|
|
998
1044
|
DOMPurify.removed = [];
|
|
999
1045
|
|
|
1046
|
+
/* Check if dirty is correctly typed for IN_PLACE */
|
|
1047
|
+
if (typeof dirty === 'string') {
|
|
1048
|
+
IN_PLACE = false;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1000
1051
|
if (IN_PLACE) {
|
|
1001
1052
|
/* No special handling necessary for in-place sanitization */
|
|
1002
1053
|
} else if (dirty instanceof Node) {
|
|
@@ -1095,8 +1146,8 @@ function createDOMPurify() {
|
|
|
1095
1146
|
|
|
1096
1147
|
/* Sanitize final string template-safe */
|
|
1097
1148
|
if (SAFE_FOR_TEMPLATES) {
|
|
1098
|
-
serializedHTML = serializedHTML
|
|
1099
|
-
serializedHTML = serializedHTML
|
|
1149
|
+
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
|
|
1150
|
+
serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' ');
|
|
1100
1151
|
}
|
|
1101
1152
|
|
|
1102
1153
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
|
@@ -1139,8 +1190,8 @@ function createDOMPurify() {
|
|
|
1139
1190
|
_parseConfig({});
|
|
1140
1191
|
}
|
|
1141
1192
|
|
|
1142
|
-
var lcTag = tag
|
|
1143
|
-
var lcName = attr
|
|
1193
|
+
var lcTag = stringToLowerCase(tag);
|
|
1194
|
+
var lcName = stringToLowerCase(attr);
|
|
1144
1195
|
return _isValidAttribute(lcTag, lcName, value);
|
|
1145
1196
|
};
|
|
1146
1197
|
|
|
@@ -1157,7 +1208,7 @@ function createDOMPurify() {
|
|
|
1157
1208
|
}
|
|
1158
1209
|
|
|
1159
1210
|
hooks[entryPoint] = hooks[entryPoint] || [];
|
|
1160
|
-
hooks[entryPoint]
|
|
1211
|
+
arrayPush(hooks[entryPoint], hookFunction);
|
|
1161
1212
|
};
|
|
1162
1213
|
|
|
1163
1214
|
/**
|
|
@@ -1169,7 +1220,7 @@ function createDOMPurify() {
|
|
|
1169
1220
|
*/
|
|
1170
1221
|
DOMPurify.removeHook = function (entryPoint) {
|
|
1171
1222
|
if (hooks[entryPoint]) {
|
|
1172
|
-
hooks[entryPoint]
|
|
1223
|
+
arrayPop(hooks[entryPoint]);
|
|
1173
1224
|
}
|
|
1174
1225
|
};
|
|
1175
1226
|
|