dompurify 3.0.1 → 3.0.2
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 +5 -5
- package/dist/purify.cjs.js +250 -415
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +251 -416
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +250 -415
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +2 -2
- package/dist/purify.min.js.map +1 -1
- package/package.json +1 -2
package/dist/purify.es.js
CHANGED
|
@@ -1,198 +1,22 @@
|
|
|
1
|
-
/*! @license DOMPurify 3.0.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function _isNativeReflectConstruct() {
|
|
23
|
-
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
|
24
|
-
if (Reflect.construct.sham) return false;
|
|
25
|
-
if (typeof Proxy === "function") return true;
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
|
|
29
|
-
return true;
|
|
30
|
-
} catch (e) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function _construct(Parent, args, Class) {
|
|
36
|
-
if (_isNativeReflectConstruct()) {
|
|
37
|
-
_construct = Reflect.construct;
|
|
38
|
-
} else {
|
|
39
|
-
_construct = function _construct(Parent, args, Class) {
|
|
40
|
-
var a = [null];
|
|
41
|
-
a.push.apply(a, args);
|
|
42
|
-
var Constructor = Function.bind.apply(Parent, a);
|
|
43
|
-
var instance = new Constructor();
|
|
44
|
-
if (Class) _setPrototypeOf(instance, Class.prototype);
|
|
45
|
-
return instance;
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return _construct.apply(null, arguments);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function _slicedToArray(arr, i) {
|
|
53
|
-
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function _toConsumableArray(arr) {
|
|
57
|
-
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function _arrayWithoutHoles(arr) {
|
|
61
|
-
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function _arrayWithHoles(arr) {
|
|
65
|
-
if (Array.isArray(arr)) return arr;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function _iterableToArray(iter) {
|
|
69
|
-
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function _iterableToArrayLimit(arr, i) {
|
|
73
|
-
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
74
|
-
|
|
75
|
-
if (_i == null) return;
|
|
76
|
-
var _arr = [];
|
|
77
|
-
var _n = true;
|
|
78
|
-
var _d = false;
|
|
79
|
-
|
|
80
|
-
var _s, _e;
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
|
|
84
|
-
_arr.push(_s.value);
|
|
85
|
-
|
|
86
|
-
if (i && _arr.length === i) break;
|
|
87
|
-
}
|
|
88
|
-
} catch (err) {
|
|
89
|
-
_d = true;
|
|
90
|
-
_e = err;
|
|
91
|
-
} finally {
|
|
92
|
-
try {
|
|
93
|
-
if (!_n && _i["return"] != null) _i["return"]();
|
|
94
|
-
} finally {
|
|
95
|
-
if (_d) throw _e;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return _arr;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function _unsupportedIterableToArray(o, minLen) {
|
|
103
|
-
if (!o) return;
|
|
104
|
-
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
105
|
-
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
106
|
-
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
107
|
-
if (n === "Map" || n === "Set") return Array.from(o);
|
|
108
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function _arrayLikeToArray(arr, len) {
|
|
112
|
-
if (len == null || len > arr.length) len = arr.length;
|
|
113
|
-
|
|
114
|
-
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
115
|
-
|
|
116
|
-
return arr2;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function _nonIterableSpread() {
|
|
120
|
-
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function _nonIterableRest() {
|
|
124
|
-
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function _createForOfIteratorHelper(o, allowArrayLike) {
|
|
128
|
-
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
|
|
129
|
-
|
|
130
|
-
if (!it) {
|
|
131
|
-
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
|
|
132
|
-
if (it) o = it;
|
|
133
|
-
var i = 0;
|
|
134
|
-
|
|
135
|
-
var F = function () {};
|
|
136
|
-
|
|
137
|
-
return {
|
|
138
|
-
s: F,
|
|
139
|
-
n: function () {
|
|
140
|
-
if (i >= o.length) return {
|
|
141
|
-
done: true
|
|
142
|
-
};
|
|
143
|
-
return {
|
|
144
|
-
done: false,
|
|
145
|
-
value: o[i++]
|
|
146
|
-
};
|
|
147
|
-
},
|
|
148
|
-
e: function (e) {
|
|
149
|
-
throw e;
|
|
150
|
-
},
|
|
151
|
-
f: F
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
var normalCompletion = true,
|
|
159
|
-
didErr = false,
|
|
160
|
-
err;
|
|
161
|
-
return {
|
|
162
|
-
s: function () {
|
|
163
|
-
it = it.call(o);
|
|
164
|
-
},
|
|
165
|
-
n: function () {
|
|
166
|
-
var step = it.next();
|
|
167
|
-
normalCompletion = step.done;
|
|
168
|
-
return step;
|
|
169
|
-
},
|
|
170
|
-
e: function (e) {
|
|
171
|
-
didErr = true;
|
|
172
|
-
err = e;
|
|
173
|
-
},
|
|
174
|
-
f: function () {
|
|
175
|
-
try {
|
|
176
|
-
if (!normalCompletion && it.return != null) it.return();
|
|
177
|
-
} finally {
|
|
178
|
-
if (didErr) throw err;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
var entries = Object.entries,
|
|
185
|
-
setPrototypeOf = Object.setPrototypeOf,
|
|
186
|
-
isFrozen = Object.isFrozen,
|
|
187
|
-
getPrototypeOf = Object.getPrototypeOf,
|
|
188
|
-
getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
189
|
-
var freeze = Object.freeze,
|
|
190
|
-
seal = Object.seal,
|
|
191
|
-
create = Object.create; // eslint-disable-line import/no-mutable-exports
|
|
192
|
-
|
|
193
|
-
var _ref = typeof Reflect !== 'undefined' && Reflect,
|
|
194
|
-
apply = _ref.apply,
|
|
195
|
-
construct = _ref.construct;
|
|
1
|
+
/*! @license DOMPurify 3.0.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.2/LICENSE */
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
entries,
|
|
5
|
+
setPrototypeOf,
|
|
6
|
+
isFrozen,
|
|
7
|
+
getPrototypeOf,
|
|
8
|
+
getOwnPropertyDescriptor
|
|
9
|
+
} = Object;
|
|
10
|
+
let {
|
|
11
|
+
freeze,
|
|
12
|
+
seal,
|
|
13
|
+
create
|
|
14
|
+
} = Object; // eslint-disable-line import/no-mutable-exports
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
apply,
|
|
18
|
+
construct
|
|
19
|
+
} = typeof Reflect !== 'undefined' && Reflect;
|
|
196
20
|
|
|
197
21
|
if (!apply) {
|
|
198
22
|
apply = function apply(fun, thisValue, args) {
|
|
@@ -214,21 +38,21 @@ if (!seal) {
|
|
|
214
38
|
|
|
215
39
|
if (!construct) {
|
|
216
40
|
construct = function construct(Func, args) {
|
|
217
|
-
return
|
|
41
|
+
return new Func(...args);
|
|
218
42
|
};
|
|
219
43
|
}
|
|
220
44
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
45
|
+
const arrayForEach = unapply(Array.prototype.forEach);
|
|
46
|
+
const arrayPop = unapply(Array.prototype.pop);
|
|
47
|
+
const arrayPush = unapply(Array.prototype.push);
|
|
48
|
+
const stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
49
|
+
const stringToString = unapply(String.prototype.toString);
|
|
50
|
+
const stringMatch = unapply(String.prototype.match);
|
|
51
|
+
const stringReplace = unapply(String.prototype.replace);
|
|
52
|
+
const stringIndexOf = unapply(String.prototype.indexOf);
|
|
53
|
+
const stringTrim = unapply(String.prototype.trim);
|
|
54
|
+
const regExpTest = unapply(RegExp.prototype.test);
|
|
55
|
+
const typeErrorCreate = unconstruct(TypeError);
|
|
232
56
|
function unapply(func) {
|
|
233
57
|
return function (thisArg) {
|
|
234
58
|
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
@@ -259,13 +83,13 @@ function addToSet(set, array, transformCaseFunc) {
|
|
|
259
83
|
setPrototypeOf(set, null);
|
|
260
84
|
}
|
|
261
85
|
|
|
262
|
-
|
|
86
|
+
let l = array.length;
|
|
263
87
|
|
|
264
88
|
while (l--) {
|
|
265
|
-
|
|
89
|
+
let element = array[l];
|
|
266
90
|
|
|
267
91
|
if (typeof element === 'string') {
|
|
268
|
-
|
|
92
|
+
const lcElement = transformCaseFunc(element);
|
|
269
93
|
|
|
270
94
|
if (lcElement !== element) {
|
|
271
95
|
// Config presets (e.g. tags.js, attrs.js) are immutable.
|
|
@@ -285,23 +109,10 @@ function addToSet(set, array, transformCaseFunc) {
|
|
|
285
109
|
/* Shallow clone an object */
|
|
286
110
|
|
|
287
111
|
function clone(object) {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
var _iterator = _createForOfIteratorHelper(entries(object)),
|
|
291
|
-
_step;
|
|
112
|
+
const newObject = create(null);
|
|
292
113
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
var _step$value = _slicedToArray(_step.value, 2),
|
|
296
|
-
property = _step$value[0],
|
|
297
|
-
value = _step$value[1];
|
|
298
|
-
|
|
299
|
-
newObject[property] = value;
|
|
300
|
-
}
|
|
301
|
-
} catch (err) {
|
|
302
|
-
_iterator.e(err);
|
|
303
|
-
} finally {
|
|
304
|
-
_iterator.f();
|
|
114
|
+
for (const [property, value] of entries(object)) {
|
|
115
|
+
newObject[property] = value;
|
|
305
116
|
}
|
|
306
117
|
|
|
307
118
|
return newObject;
|
|
@@ -311,7 +122,7 @@ function clone(object) {
|
|
|
311
122
|
|
|
312
123
|
function lookupGetter(object, prop) {
|
|
313
124
|
while (object !== null) {
|
|
314
|
-
|
|
125
|
+
const desc = getOwnPropertyDescriptor(object, prop);
|
|
315
126
|
|
|
316
127
|
if (desc) {
|
|
317
128
|
if (desc.get) {
|
|
@@ -334,44 +145,55 @@ function lookupGetter(object, prop) {
|
|
|
334
145
|
return fallbackValue;
|
|
335
146
|
}
|
|
336
147
|
|
|
337
|
-
|
|
148
|
+
const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', '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']); // SVG
|
|
338
149
|
|
|
339
|
-
|
|
340
|
-
|
|
150
|
+
const svg$1 = 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']);
|
|
151
|
+
const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']); // List of SVG elements that are disallowed by default.
|
|
341
152
|
// We still need to know them so that we can do namespace
|
|
342
153
|
// checks properly in case one wants to add them to
|
|
343
154
|
// allow-list.
|
|
344
155
|
|
|
345
|
-
|
|
346
|
-
|
|
156
|
+
const svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', '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']);
|
|
157
|
+
const mathMl$1 = 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', 'mprescripts']); // Similarly to SVG, we want to know all MathML elements,
|
|
347
158
|
// even those that we disallow by default.
|
|
348
159
|
|
|
349
|
-
|
|
350
|
-
|
|
160
|
+
const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
161
|
+
const text = freeze(['#text']);
|
|
351
162
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
163
|
+
const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', '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', 'nonce', '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']);
|
|
164
|
+
const svg = 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', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
|
|
165
|
+
const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
|
|
166
|
+
const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
356
167
|
|
|
357
|
-
|
|
168
|
+
const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
|
|
358
169
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
170
|
+
const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
|
|
171
|
+
const TMPLIT_EXPR = seal(/\${[\w\W]*}/gm);
|
|
172
|
+
const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
|
|
362
173
|
|
|
363
|
-
|
|
174
|
+
const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
|
|
364
175
|
|
|
365
|
-
|
|
176
|
+
const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
|
|
366
177
|
);
|
|
367
|
-
|
|
368
|
-
|
|
178
|
+
const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
|
|
179
|
+
const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
|
|
369
180
|
);
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
var
|
|
373
|
-
|
|
374
|
-
|
|
181
|
+
const DOCTYPE_NAME = seal(/^html$/i);
|
|
182
|
+
|
|
183
|
+
var EXPRESSIONS = /*#__PURE__*/Object.freeze({
|
|
184
|
+
__proto__: null,
|
|
185
|
+
MUSTACHE_EXPR: MUSTACHE_EXPR,
|
|
186
|
+
ERB_EXPR: ERB_EXPR,
|
|
187
|
+
TMPLIT_EXPR: TMPLIT_EXPR,
|
|
188
|
+
DATA_ATTR: DATA_ATTR,
|
|
189
|
+
ARIA_ATTR: ARIA_ATTR,
|
|
190
|
+
IS_ALLOWED_URI: IS_ALLOWED_URI,
|
|
191
|
+
IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
|
|
192
|
+
ATTR_WHITESPACE: ATTR_WHITESPACE,
|
|
193
|
+
DOCTYPE_NAME: DOCTYPE_NAME
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const getGlobal = () => typeof window === 'undefined' ? null : window;
|
|
375
197
|
/**
|
|
376
198
|
* Creates a no-op policy for internal use only.
|
|
377
199
|
* Don't export this function outside this module!
|
|
@@ -382,31 +204,33 @@ var getGlobal = function getGlobal() {
|
|
|
382
204
|
*/
|
|
383
205
|
|
|
384
206
|
|
|
385
|
-
|
|
386
|
-
if (
|
|
207
|
+
const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
|
|
208
|
+
if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
|
|
387
209
|
return null;
|
|
388
210
|
} // Allow the callers to control the unique policy name
|
|
389
211
|
// by adding a data-tt-policy-suffix to the script element with the DOMPurify.
|
|
390
212
|
// Policy creation with duplicate names throws in Trusted Types.
|
|
391
213
|
|
|
392
214
|
|
|
393
|
-
|
|
394
|
-
|
|
215
|
+
let suffix = null;
|
|
216
|
+
const ATTR_NAME = 'data-tt-policy-suffix';
|
|
395
217
|
|
|
396
218
|
if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
|
|
397
219
|
suffix = document.currentScript.getAttribute(ATTR_NAME);
|
|
398
220
|
}
|
|
399
221
|
|
|
400
|
-
|
|
222
|
+
const policyName = 'dompurify' + (suffix ? '#' + suffix : '');
|
|
401
223
|
|
|
402
224
|
try {
|
|
403
225
|
return trustedTypes.createPolicy(policyName, {
|
|
404
|
-
createHTML
|
|
226
|
+
createHTML(html) {
|
|
405
227
|
return html;
|
|
406
228
|
},
|
|
407
|
-
|
|
229
|
+
|
|
230
|
+
createScriptURL(scriptUrl) {
|
|
408
231
|
return scriptUrl;
|
|
409
232
|
}
|
|
233
|
+
|
|
410
234
|
});
|
|
411
235
|
} catch (_) {
|
|
412
236
|
// Policy creation failed (most likely another DOMPurify script has
|
|
@@ -418,18 +242,16 @@ var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes,
|
|
|
418
242
|
};
|
|
419
243
|
|
|
420
244
|
function createDOMPurify() {
|
|
421
|
-
|
|
245
|
+
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
422
246
|
|
|
423
|
-
|
|
424
|
-
return createDOMPurify(root);
|
|
425
|
-
};
|
|
247
|
+
const DOMPurify = root => createDOMPurify(root);
|
|
426
248
|
/**
|
|
427
249
|
* Version label, exposed for easier checks
|
|
428
250
|
* if DOMPurify is up to date or not
|
|
429
251
|
*/
|
|
430
252
|
|
|
431
253
|
|
|
432
|
-
DOMPurify.version = '3.0.
|
|
254
|
+
DOMPurify.version = '3.0.2';
|
|
433
255
|
/**
|
|
434
256
|
* Array of elements that DOMPurify removed during sanitation.
|
|
435
257
|
* Empty if nothing was removed.
|
|
@@ -444,23 +266,26 @@ function createDOMPurify() {
|
|
|
444
266
|
return DOMPurify;
|
|
445
267
|
}
|
|
446
268
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
269
|
+
const originalDocument = window.document;
|
|
270
|
+
let {
|
|
271
|
+
document
|
|
272
|
+
} = window;
|
|
273
|
+
const {
|
|
274
|
+
DocumentFragment,
|
|
275
|
+
HTMLTemplateElement,
|
|
276
|
+
Node,
|
|
277
|
+
Element,
|
|
278
|
+
NodeFilter,
|
|
279
|
+
NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,
|
|
280
|
+
HTMLFormElement,
|
|
281
|
+
DOMParser,
|
|
282
|
+
trustedTypes
|
|
283
|
+
} = window;
|
|
284
|
+
const ElementPrototype = Element.prototype;
|
|
285
|
+
const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
|
|
286
|
+
const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
|
|
287
|
+
const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
|
|
288
|
+
const getParentNode = lookupGetter(ElementPrototype, 'parentNode'); // As per issue #47, the web-components registry is inherited by a
|
|
464
289
|
// new document created via createHTMLDocument. As per the spec
|
|
465
290
|
// (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
|
|
466
291
|
// a new empty registry is used when creating a template contents owner
|
|
@@ -468,36 +293,43 @@ function createDOMPurify() {
|
|
|
468
293
|
// is inherited.
|
|
469
294
|
|
|
470
295
|
if (typeof HTMLTemplateElement === 'function') {
|
|
471
|
-
|
|
296
|
+
const template = document.createElement('template');
|
|
472
297
|
|
|
473
298
|
if (template.content && template.content.ownerDocument) {
|
|
474
299
|
document = template.content.ownerDocument;
|
|
475
300
|
}
|
|
476
301
|
}
|
|
477
302
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
303
|
+
const trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
|
|
304
|
+
|
|
305
|
+
const emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
|
|
306
|
+
const {
|
|
307
|
+
implementation,
|
|
308
|
+
createNodeIterator,
|
|
309
|
+
createDocumentFragment,
|
|
310
|
+
getElementsByTagName
|
|
311
|
+
} = document;
|
|
312
|
+
const {
|
|
313
|
+
importNode
|
|
314
|
+
} = originalDocument;
|
|
315
|
+
let hooks = {};
|
|
488
316
|
/**
|
|
489
317
|
* Expose whether this browser supports running the full DOMPurify.
|
|
490
318
|
*/
|
|
491
319
|
|
|
492
320
|
DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined';
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
321
|
+
const {
|
|
322
|
+
MUSTACHE_EXPR,
|
|
323
|
+
ERB_EXPR,
|
|
324
|
+
TMPLIT_EXPR,
|
|
325
|
+
DATA_ATTR,
|
|
326
|
+
ARIA_ATTR,
|
|
327
|
+
IS_SCRIPT_OR_DATA,
|
|
328
|
+
ATTR_WHITESPACE
|
|
329
|
+
} = EXPRESSIONS;
|
|
330
|
+
let {
|
|
331
|
+
IS_ALLOWED_URI: IS_ALLOWED_URI$1
|
|
332
|
+
} = EXPRESSIONS;
|
|
501
333
|
/**
|
|
502
334
|
* We consider the elements and attributes below to be safe. Ideally
|
|
503
335
|
* don't add any new ones but feel free to remove unwanted ones.
|
|
@@ -505,12 +337,12 @@ function createDOMPurify() {
|
|
|
505
337
|
|
|
506
338
|
/* allowed element names */
|
|
507
339
|
|
|
508
|
-
|
|
509
|
-
|
|
340
|
+
let ALLOWED_TAGS = null;
|
|
341
|
+
const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);
|
|
510
342
|
/* Allowed attribute names */
|
|
511
343
|
|
|
512
|
-
|
|
513
|
-
|
|
344
|
+
let ALLOWED_ATTR = null;
|
|
345
|
+
const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);
|
|
514
346
|
/*
|
|
515
347
|
* Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.
|
|
516
348
|
* @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
|
|
@@ -518,7 +350,7 @@ function createDOMPurify() {
|
|
|
518
350
|
* @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
|
|
519
351
|
*/
|
|
520
352
|
|
|
521
|
-
|
|
353
|
+
let CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
|
|
522
354
|
tagNameCheck: {
|
|
523
355
|
writable: true,
|
|
524
356
|
configurable: false,
|
|
@@ -540,57 +372,57 @@ function createDOMPurify() {
|
|
|
540
372
|
}));
|
|
541
373
|
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
|
|
542
374
|
|
|
543
|
-
|
|
375
|
+
let FORBID_TAGS = null;
|
|
544
376
|
/* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
|
|
545
377
|
|
|
546
|
-
|
|
378
|
+
let FORBID_ATTR = null;
|
|
547
379
|
/* Decide if ARIA attributes are okay */
|
|
548
380
|
|
|
549
|
-
|
|
381
|
+
let ALLOW_ARIA_ATTR = true;
|
|
550
382
|
/* Decide if custom data attributes are okay */
|
|
551
383
|
|
|
552
|
-
|
|
384
|
+
let ALLOW_DATA_ATTR = true;
|
|
553
385
|
/* Decide if unknown protocols are okay */
|
|
554
386
|
|
|
555
|
-
|
|
387
|
+
let ALLOW_UNKNOWN_PROTOCOLS = false;
|
|
556
388
|
/* Decide if self-closing tags in attributes are allowed.
|
|
557
389
|
* Usually removed due to a mXSS issue in jQuery 3.0 */
|
|
558
390
|
|
|
559
|
-
|
|
391
|
+
let ALLOW_SELF_CLOSE_IN_ATTR = true;
|
|
560
392
|
/* Output should be safe for common template engines.
|
|
561
393
|
* This means, DOMPurify removes data attributes, mustaches and ERB
|
|
562
394
|
*/
|
|
563
395
|
|
|
564
|
-
|
|
396
|
+
let SAFE_FOR_TEMPLATES = false;
|
|
565
397
|
/* Decide if document with <html>... should be returned */
|
|
566
398
|
|
|
567
|
-
|
|
399
|
+
let WHOLE_DOCUMENT = false;
|
|
568
400
|
/* Track whether config is already set on this instance of DOMPurify. */
|
|
569
401
|
|
|
570
|
-
|
|
402
|
+
let SET_CONFIG = false;
|
|
571
403
|
/* Decide if all elements (e.g. style, script) must be children of
|
|
572
404
|
* document.body. By default, browsers might move them to document.head */
|
|
573
405
|
|
|
574
|
-
|
|
406
|
+
let FORCE_BODY = false;
|
|
575
407
|
/* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
|
|
576
408
|
* string (or a TrustedHTML object if Trusted Types are supported).
|
|
577
409
|
* If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
|
|
578
410
|
*/
|
|
579
411
|
|
|
580
|
-
|
|
412
|
+
let RETURN_DOM = false;
|
|
581
413
|
/* Decide if a DOM `DocumentFragment` should be returned, instead of a html
|
|
582
414
|
* string (or a TrustedHTML object if Trusted Types are supported) */
|
|
583
415
|
|
|
584
|
-
|
|
416
|
+
let RETURN_DOM_FRAGMENT = false;
|
|
585
417
|
/* Try to return a Trusted Type object instead of a string, return a string in
|
|
586
418
|
* case Trusted Types are not supported */
|
|
587
419
|
|
|
588
|
-
|
|
420
|
+
let RETURN_TRUSTED_TYPE = false;
|
|
589
421
|
/* Output should be free from DOM clobbering attacks?
|
|
590
422
|
* This sanitizes markups named with colliding, clobberable built-in DOM APIs.
|
|
591
423
|
*/
|
|
592
424
|
|
|
593
|
-
|
|
425
|
+
let SANITIZE_DOM = true;
|
|
594
426
|
/* Achieve full DOM Clobbering protection by isolating the namespace of named
|
|
595
427
|
* properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.
|
|
596
428
|
*
|
|
@@ -605,57 +437,57 @@ function createDOMPurify() {
|
|
|
605
437
|
* with a constant string, i.e., `user-content-`
|
|
606
438
|
*/
|
|
607
439
|
|
|
608
|
-
|
|
609
|
-
|
|
440
|
+
let SANITIZE_NAMED_PROPS = false;
|
|
441
|
+
const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';
|
|
610
442
|
/* Keep element content when removing element? */
|
|
611
443
|
|
|
612
|
-
|
|
444
|
+
let KEEP_CONTENT = true;
|
|
613
445
|
/* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
|
|
614
446
|
* of importing it into a new Document and returning a sanitized copy */
|
|
615
447
|
|
|
616
|
-
|
|
448
|
+
let IN_PLACE = false;
|
|
617
449
|
/* Allow usage of profiles like html, svg and mathMl */
|
|
618
450
|
|
|
619
|
-
|
|
451
|
+
let USE_PROFILES = {};
|
|
620
452
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
621
453
|
|
|
622
|
-
|
|
623
|
-
|
|
454
|
+
let FORBID_CONTENTS = null;
|
|
455
|
+
const DEFAULT_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']);
|
|
624
456
|
/* Tags that are safe for data: URIs */
|
|
625
457
|
|
|
626
|
-
|
|
627
|
-
|
|
458
|
+
let DATA_URI_TAGS = null;
|
|
459
|
+
const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);
|
|
628
460
|
/* Attributes safe for values like "javascript:" */
|
|
629
461
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
462
|
+
let URI_SAFE_ATTRIBUTES = null;
|
|
463
|
+
const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
|
|
464
|
+
const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
|
|
465
|
+
const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
466
|
+
const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
|
|
635
467
|
/* Document namespace */
|
|
636
468
|
|
|
637
|
-
|
|
638
|
-
|
|
469
|
+
let NAMESPACE = HTML_NAMESPACE;
|
|
470
|
+
let IS_EMPTY_INPUT = false;
|
|
639
471
|
/* Allowed XHTML+XML namespaces */
|
|
640
472
|
|
|
641
|
-
|
|
642
|
-
|
|
473
|
+
let ALLOWED_NAMESPACES = null;
|
|
474
|
+
const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
|
|
643
475
|
/* Parsing of strict XHTML documents */
|
|
644
476
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
477
|
+
let PARSER_MEDIA_TYPE;
|
|
478
|
+
const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
|
|
479
|
+
const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
|
|
480
|
+
let transformCaseFunc;
|
|
649
481
|
/* Keep a reference to config to pass to hooks */
|
|
650
482
|
|
|
651
|
-
|
|
483
|
+
let CONFIG = null;
|
|
652
484
|
/* Ideally, do not touch anything below this line */
|
|
653
485
|
|
|
654
486
|
/* ______________________________________________ */
|
|
655
487
|
|
|
656
|
-
|
|
488
|
+
const formElement = document.createElement('form');
|
|
657
489
|
|
|
658
|
-
|
|
490
|
+
const isRegexOrFunction = function isRegexOrFunction(testValue) {
|
|
659
491
|
return testValue instanceof RegExp || testValue instanceof Function;
|
|
660
492
|
};
|
|
661
493
|
/**
|
|
@@ -666,14 +498,14 @@ function createDOMPurify() {
|
|
|
666
498
|
// eslint-disable-next-line complexity
|
|
667
499
|
|
|
668
500
|
|
|
669
|
-
|
|
501
|
+
const _parseConfig = function _parseConfig(cfg) {
|
|
670
502
|
if (CONFIG && CONFIG === cfg) {
|
|
671
503
|
return;
|
|
672
504
|
}
|
|
673
505
|
/* Shield configuration object from tampering */
|
|
674
506
|
|
|
675
507
|
|
|
676
|
-
if (!cfg ||
|
|
508
|
+
if (!cfg || typeof cfg !== 'object') {
|
|
677
509
|
cfg = {};
|
|
678
510
|
}
|
|
679
511
|
/* Shield configuration object from prototype pollution */
|
|
@@ -731,7 +563,7 @@ function createDOMPurify() {
|
|
|
731
563
|
|
|
732
564
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
733
565
|
|
|
734
|
-
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI
|
|
566
|
+
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;
|
|
735
567
|
NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
|
|
736
568
|
CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
|
|
737
569
|
|
|
@@ -758,7 +590,7 @@ function createDOMPurify() {
|
|
|
758
590
|
|
|
759
591
|
|
|
760
592
|
if (USE_PROFILES) {
|
|
761
|
-
ALLOWED_TAGS = addToSet({},
|
|
593
|
+
ALLOWED_TAGS = addToSet({}, [...text]);
|
|
762
594
|
ALLOWED_ATTR = [];
|
|
763
595
|
|
|
764
596
|
if (USE_PROFILES.html === true) {
|
|
@@ -843,21 +675,21 @@ function createDOMPurify() {
|
|
|
843
675
|
CONFIG = cfg;
|
|
844
676
|
};
|
|
845
677
|
|
|
846
|
-
|
|
847
|
-
|
|
678
|
+
const MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
|
|
679
|
+
const HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']); // Certain elements are allowed in both SVG and HTML
|
|
848
680
|
// namespace. We need to specify them explicitly
|
|
849
681
|
// so that they don't get erroneously deleted from
|
|
850
682
|
// HTML namespace.
|
|
851
683
|
|
|
852
|
-
|
|
684
|
+
const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
|
|
853
685
|
/* Keep track of all possible SVG and MathML tags
|
|
854
686
|
* so that we can perform the namespace checks
|
|
855
687
|
* correctly. */
|
|
856
688
|
|
|
857
|
-
|
|
689
|
+
const ALL_SVG_TAGS = addToSet({}, svg$1);
|
|
858
690
|
addToSet(ALL_SVG_TAGS, svgFilters);
|
|
859
691
|
addToSet(ALL_SVG_TAGS, svgDisallowed);
|
|
860
|
-
|
|
692
|
+
const ALL_MATHML_TAGS = addToSet({}, mathMl$1);
|
|
861
693
|
addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
|
|
862
694
|
/**
|
|
863
695
|
*
|
|
@@ -868,8 +700,8 @@ function createDOMPurify() {
|
|
|
868
700
|
* return. Return true otherwise.
|
|
869
701
|
*/
|
|
870
702
|
|
|
871
|
-
|
|
872
|
-
|
|
703
|
+
const _checkValidNamespace = function _checkValidNamespace(element) {
|
|
704
|
+
let parent = getParentNode(element); // In JSDOM, if we're inside shadow DOM, then parentNode
|
|
873
705
|
// can be null. We just simulate parent in this case.
|
|
874
706
|
|
|
875
707
|
if (!parent || !parent.tagName) {
|
|
@@ -879,8 +711,8 @@ function createDOMPurify() {
|
|
|
879
711
|
};
|
|
880
712
|
}
|
|
881
713
|
|
|
882
|
-
|
|
883
|
-
|
|
714
|
+
const tagName = stringToLowerCase(element.tagName);
|
|
715
|
+
const parentTagName = stringToLowerCase(parent.tagName);
|
|
884
716
|
|
|
885
717
|
if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
|
|
886
718
|
return false;
|
|
@@ -960,7 +792,7 @@ function createDOMPurify() {
|
|
|
960
792
|
*/
|
|
961
793
|
|
|
962
794
|
|
|
963
|
-
|
|
795
|
+
const _forceRemove = function _forceRemove(node) {
|
|
964
796
|
arrayPush(DOMPurify.removed, {
|
|
965
797
|
element: node
|
|
966
798
|
});
|
|
@@ -980,7 +812,7 @@ function createDOMPurify() {
|
|
|
980
812
|
*/
|
|
981
813
|
|
|
982
814
|
|
|
983
|
-
|
|
815
|
+
const _removeAttribute = function _removeAttribute(name, node) {
|
|
984
816
|
try {
|
|
985
817
|
arrayPush(DOMPurify.removed, {
|
|
986
818
|
attribute: node.getAttributeNode(name),
|
|
@@ -1015,16 +847,16 @@ function createDOMPurify() {
|
|
|
1015
847
|
*/
|
|
1016
848
|
|
|
1017
849
|
|
|
1018
|
-
|
|
850
|
+
const _initDocument = function _initDocument(dirty) {
|
|
1019
851
|
/* Create a HTML document */
|
|
1020
|
-
|
|
1021
|
-
|
|
852
|
+
let doc;
|
|
853
|
+
let leadingWhitespace;
|
|
1022
854
|
|
|
1023
855
|
if (FORCE_BODY) {
|
|
1024
856
|
dirty = '<remove></remove>' + dirty;
|
|
1025
857
|
} else {
|
|
1026
858
|
/* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
|
|
1027
|
-
|
|
859
|
+
const matches = stringMatch(dirty, /^[\r\n\t ]+/);
|
|
1028
860
|
leadingWhitespace = matches && matches[0];
|
|
1029
861
|
}
|
|
1030
862
|
|
|
@@ -1033,7 +865,7 @@ function createDOMPurify() {
|
|
|
1033
865
|
dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
|
|
1034
866
|
}
|
|
1035
867
|
|
|
1036
|
-
|
|
868
|
+
const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
1037
869
|
/*
|
|
1038
870
|
* Use the DOMParser API by default, fallback later if needs be
|
|
1039
871
|
* DOMParser not work for svg when has multiple root element.
|
|
@@ -1056,7 +888,7 @@ function createDOMPurify() {
|
|
|
1056
888
|
}
|
|
1057
889
|
}
|
|
1058
890
|
|
|
1059
|
-
|
|
891
|
+
const body = doc.body || doc.documentElement;
|
|
1060
892
|
|
|
1061
893
|
if (dirty && leadingWhitespace) {
|
|
1062
894
|
body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
|
|
@@ -1078,7 +910,7 @@ function createDOMPurify() {
|
|
|
1078
910
|
*/
|
|
1079
911
|
|
|
1080
912
|
|
|
1081
|
-
|
|
913
|
+
const _createIterator = function _createIterator(root) {
|
|
1082
914
|
return createNodeIterator.call(root.ownerDocument || root, root, // eslint-disable-next-line no-bitwise
|
|
1083
915
|
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
|
|
1084
916
|
};
|
|
@@ -1090,7 +922,7 @@ function createDOMPurify() {
|
|
|
1090
922
|
*/
|
|
1091
923
|
|
|
1092
924
|
|
|
1093
|
-
|
|
925
|
+
const _isClobbered = function _isClobbered(elm) {
|
|
1094
926
|
return elm instanceof HTMLFormElement && (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' || typeof elm.hasChildNodes !== 'function');
|
|
1095
927
|
};
|
|
1096
928
|
/**
|
|
@@ -1101,8 +933,8 @@ function createDOMPurify() {
|
|
|
1101
933
|
*/
|
|
1102
934
|
|
|
1103
935
|
|
|
1104
|
-
|
|
1105
|
-
return
|
|
936
|
+
const _isNode = function _isNode(object) {
|
|
937
|
+
return typeof Node === 'object' ? object instanceof Node : object && typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
|
|
1106
938
|
};
|
|
1107
939
|
/**
|
|
1108
940
|
* _executeHook
|
|
@@ -1114,12 +946,12 @@ function createDOMPurify() {
|
|
|
1114
946
|
*/
|
|
1115
947
|
|
|
1116
948
|
|
|
1117
|
-
|
|
949
|
+
const _executeHook = function _executeHook(entryPoint, currentNode, data) {
|
|
1118
950
|
if (!hooks[entryPoint]) {
|
|
1119
951
|
return;
|
|
1120
952
|
}
|
|
1121
953
|
|
|
1122
|
-
arrayForEach(hooks[entryPoint],
|
|
954
|
+
arrayForEach(hooks[entryPoint], hook => {
|
|
1123
955
|
hook.call(DOMPurify, currentNode, data, CONFIG);
|
|
1124
956
|
});
|
|
1125
957
|
};
|
|
@@ -1135,8 +967,8 @@ function createDOMPurify() {
|
|
|
1135
967
|
*/
|
|
1136
968
|
|
|
1137
969
|
|
|
1138
|
-
|
|
1139
|
-
|
|
970
|
+
const _sanitizeElements = function _sanitizeElements(currentNode) {
|
|
971
|
+
let content;
|
|
1140
972
|
/* Execute a hook if present */
|
|
1141
973
|
|
|
1142
974
|
_executeHook('beforeSanitizeElements', currentNode, null);
|
|
@@ -1151,11 +983,11 @@ function createDOMPurify() {
|
|
|
1151
983
|
/* Now let's check the element's type and name */
|
|
1152
984
|
|
|
1153
985
|
|
|
1154
|
-
|
|
986
|
+
const tagName = transformCaseFunc(currentNode.nodeName);
|
|
1155
987
|
/* Execute a hook if present */
|
|
1156
988
|
|
|
1157
989
|
_executeHook('uponSanitizeElement', currentNode, {
|
|
1158
|
-
tagName
|
|
990
|
+
tagName,
|
|
1159
991
|
allowedTags: ALLOWED_TAGS
|
|
1160
992
|
});
|
|
1161
993
|
/* Detect mXSS attempts abusing namespace confusion */
|
|
@@ -1179,13 +1011,13 @@ function createDOMPurify() {
|
|
|
1179
1011
|
|
|
1180
1012
|
|
|
1181
1013
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
1182
|
-
|
|
1183
|
-
|
|
1014
|
+
const parentNode = getParentNode(currentNode) || currentNode.parentNode;
|
|
1015
|
+
const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
|
|
1184
1016
|
|
|
1185
1017
|
if (childNodes && parentNode) {
|
|
1186
|
-
|
|
1018
|
+
const childCount = childNodes.length;
|
|
1187
1019
|
|
|
1188
|
-
for (
|
|
1020
|
+
for (let i = childCount - 1; i >= 0; --i) {
|
|
1189
1021
|
parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
|
|
1190
1022
|
}
|
|
1191
1023
|
}
|
|
@@ -1217,9 +1049,9 @@ function createDOMPurify() {
|
|
|
1217
1049
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
|
1218
1050
|
/* Get the element's text content */
|
|
1219
1051
|
content = currentNode.textContent;
|
|
1220
|
-
content = stringReplace(content, MUSTACHE_EXPR
|
|
1221
|
-
content = stringReplace(content, ERB_EXPR
|
|
1222
|
-
content = stringReplace(content, TMPLIT_EXPR
|
|
1052
|
+
content = stringReplace(content, MUSTACHE_EXPR, ' ');
|
|
1053
|
+
content = stringReplace(content, ERB_EXPR, ' ');
|
|
1054
|
+
content = stringReplace(content, TMPLIT_EXPR, ' ');
|
|
1223
1055
|
|
|
1224
1056
|
if (currentNode.textContent !== content) {
|
|
1225
1057
|
arrayPush(DOMPurify.removed, {
|
|
@@ -1246,7 +1078,7 @@ function createDOMPurify() {
|
|
|
1246
1078
|
// eslint-disable-next-line complexity
|
|
1247
1079
|
|
|
1248
1080
|
|
|
1249
|
-
|
|
1081
|
+
const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
1250
1082
|
/* Make sure attribute cannot clobber */
|
|
1251
1083
|
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
1252
1084
|
return false;
|
|
@@ -1257,7 +1089,7 @@ function createDOMPurify() {
|
|
|
1257
1089
|
We don't need to check the value; it's always URI safe. */
|
|
1258
1090
|
|
|
1259
1091
|
|
|
1260
|
-
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR
|
|
1092
|
+
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
1261
1093
|
if ( // First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
1262
1094
|
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1263
1095
|
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
|
|
@@ -1268,7 +1100,7 @@ function createDOMPurify() {
|
|
|
1268
1100
|
}
|
|
1269
1101
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
1270
1102
|
|
|
1271
|
-
} else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE
|
|
1103
|
+
} else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (!value) ; else {
|
|
1272
1104
|
return false;
|
|
1273
1105
|
}
|
|
1274
1106
|
|
|
@@ -1282,7 +1114,7 @@ function createDOMPurify() {
|
|
|
1282
1114
|
*/
|
|
1283
1115
|
|
|
1284
1116
|
|
|
1285
|
-
|
|
1117
|
+
const _basicCustomElementTest = function _basicCustomElementTest(tagName) {
|
|
1286
1118
|
return tagName.indexOf('-') > 0;
|
|
1287
1119
|
};
|
|
1288
1120
|
/**
|
|
@@ -1297,23 +1129,25 @@ function createDOMPurify() {
|
|
|
1297
1129
|
*/
|
|
1298
1130
|
|
|
1299
1131
|
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1132
|
+
const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
1133
|
+
let attr;
|
|
1134
|
+
let value;
|
|
1135
|
+
let lcName;
|
|
1136
|
+
let l;
|
|
1305
1137
|
/* Execute a hook if present */
|
|
1306
1138
|
|
|
1307
1139
|
_executeHook('beforeSanitizeAttributes', currentNode, null);
|
|
1308
1140
|
|
|
1309
|
-
|
|
1141
|
+
const {
|
|
1142
|
+
attributes
|
|
1143
|
+
} = currentNode;
|
|
1310
1144
|
/* Check if we have attributes; if not we might have a text node */
|
|
1311
1145
|
|
|
1312
1146
|
if (!attributes) {
|
|
1313
1147
|
return;
|
|
1314
1148
|
}
|
|
1315
1149
|
|
|
1316
|
-
|
|
1150
|
+
const hookEvent = {
|
|
1317
1151
|
attrName: '',
|
|
1318
1152
|
attrValue: '',
|
|
1319
1153
|
keepAttr: true,
|
|
@@ -1324,9 +1158,10 @@ function createDOMPurify() {
|
|
|
1324
1158
|
|
|
1325
1159
|
while (l--) {
|
|
1326
1160
|
attr = attributes[l];
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1161
|
+
const {
|
|
1162
|
+
name,
|
|
1163
|
+
namespaceURI
|
|
1164
|
+
} = attr;
|
|
1330
1165
|
value = name === 'value' ? attr.value : stringTrim(attr.value);
|
|
1331
1166
|
lcName = transformCaseFunc(name);
|
|
1332
1167
|
/* Execute a hook if present */
|
|
@@ -1366,14 +1201,14 @@ function createDOMPurify() {
|
|
|
1366
1201
|
|
|
1367
1202
|
|
|
1368
1203
|
if (SAFE_FOR_TEMPLATES) {
|
|
1369
|
-
value = stringReplace(value, MUSTACHE_EXPR
|
|
1370
|
-
value = stringReplace(value, ERB_EXPR
|
|
1371
|
-
value = stringReplace(value, TMPLIT_EXPR
|
|
1204
|
+
value = stringReplace(value, MUSTACHE_EXPR, ' ');
|
|
1205
|
+
value = stringReplace(value, ERB_EXPR, ' ');
|
|
1206
|
+
value = stringReplace(value, TMPLIT_EXPR, ' ');
|
|
1372
1207
|
}
|
|
1373
1208
|
/* Is `value` valid for this attribute? */
|
|
1374
1209
|
|
|
1375
1210
|
|
|
1376
|
-
|
|
1211
|
+
const lcTag = transformCaseFunc(currentNode.nodeName);
|
|
1377
1212
|
|
|
1378
1213
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
1379
1214
|
continue;
|
|
@@ -1393,7 +1228,7 @@ function createDOMPurify() {
|
|
|
1393
1228
|
/* Handle attributes that require Trusted Types */
|
|
1394
1229
|
|
|
1395
1230
|
|
|
1396
|
-
if (trustedTypesPolicy &&
|
|
1231
|
+
if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {
|
|
1397
1232
|
if (namespaceURI) ; else {
|
|
1398
1233
|
switch (trustedTypes.getAttributeType(lcTag, lcName)) {
|
|
1399
1234
|
case 'TrustedHTML':
|
|
@@ -1432,10 +1267,10 @@ function createDOMPurify() {
|
|
|
1432
1267
|
*/
|
|
1433
1268
|
|
|
1434
1269
|
|
|
1435
|
-
|
|
1436
|
-
|
|
1270
|
+
const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
|
|
1271
|
+
let shadowNode;
|
|
1437
1272
|
|
|
1438
|
-
|
|
1273
|
+
const shadowIterator = _createIterator(fragment);
|
|
1439
1274
|
/* Execute a hook if present */
|
|
1440
1275
|
|
|
1441
1276
|
|
|
@@ -1477,11 +1312,11 @@ function createDOMPurify() {
|
|
|
1477
1312
|
|
|
1478
1313
|
|
|
1479
1314
|
DOMPurify.sanitize = function (dirty) {
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1315
|
+
let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
1316
|
+
let body;
|
|
1317
|
+
let importedNode;
|
|
1318
|
+
let currentNode;
|
|
1319
|
+
let returnNode;
|
|
1485
1320
|
/* Make sure we have a string to sanitize.
|
|
1486
1321
|
DO NOT return early, as this will return the wrong type if
|
|
1487
1322
|
the user has requested a DOM object rather than a string */
|
|
@@ -1531,7 +1366,7 @@ function createDOMPurify() {
|
|
|
1531
1366
|
if (IN_PLACE) {
|
|
1532
1367
|
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
1533
1368
|
if (dirty.nodeName) {
|
|
1534
|
-
|
|
1369
|
+
const tagName = transformCaseFunc(dirty.nodeName);
|
|
1535
1370
|
|
|
1536
1371
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
1537
1372
|
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
@@ -1577,7 +1412,7 @@ function createDOMPurify() {
|
|
|
1577
1412
|
/* Get node iterator */
|
|
1578
1413
|
|
|
1579
1414
|
|
|
1580
|
-
|
|
1415
|
+
const nodeIterator = _createIterator(IN_PLACE ? dirty : body);
|
|
1581
1416
|
/* Now start iterating over the created document */
|
|
1582
1417
|
|
|
1583
1418
|
|
|
@@ -1632,7 +1467,7 @@ function createDOMPurify() {
|
|
|
1632
1467
|
return returnNode;
|
|
1633
1468
|
}
|
|
1634
1469
|
|
|
1635
|
-
|
|
1470
|
+
let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
|
1636
1471
|
/* Serialize doctype if allowed */
|
|
1637
1472
|
|
|
1638
1473
|
if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
|
|
@@ -1642,9 +1477,9 @@ function createDOMPurify() {
|
|
|
1642
1477
|
|
|
1643
1478
|
|
|
1644
1479
|
if (SAFE_FOR_TEMPLATES) {
|
|
1645
|
-
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR
|
|
1646
|
-
serializedHTML = stringReplace(serializedHTML, ERB_EXPR
|
|
1647
|
-
serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR
|
|
1480
|
+
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR, ' ');
|
|
1481
|
+
serializedHTML = stringReplace(serializedHTML, ERB_EXPR, ' ');
|
|
1482
|
+
serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR, ' ');
|
|
1648
1483
|
}
|
|
1649
1484
|
|
|
1650
1485
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
|
@@ -1691,8 +1526,8 @@ function createDOMPurify() {
|
|
|
1691
1526
|
_parseConfig({});
|
|
1692
1527
|
}
|
|
1693
1528
|
|
|
1694
|
-
|
|
1695
|
-
|
|
1529
|
+
const lcTag = transformCaseFunc(tag);
|
|
1530
|
+
const lcName = transformCaseFunc(attr);
|
|
1696
1531
|
return _isValidAttribute(lcTag, lcName, value);
|
|
1697
1532
|
};
|
|
1698
1533
|
/**
|