dompurify 3.0.0 → 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 +6 -6
- package/dist/purify.cjs.js +251 -415
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +252 -416
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +251 -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.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @license DOMPurify 3.0.
|
|
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
2
|
|
|
3
3
|
(function (global, factory) {
|
|
4
4
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
@@ -6,199 +6,23 @@
|
|
|
6
6
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.DOMPurify = factory());
|
|
7
7
|
})(this, (function () { 'use strict';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function _isNativeReflectConstruct() {
|
|
29
|
-
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
|
30
|
-
if (Reflect.construct.sham) return false;
|
|
31
|
-
if (typeof Proxy === "function") return true;
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
|
|
35
|
-
return true;
|
|
36
|
-
} catch (e) {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function _construct(Parent, args, Class) {
|
|
42
|
-
if (_isNativeReflectConstruct()) {
|
|
43
|
-
_construct = Reflect.construct;
|
|
44
|
-
} else {
|
|
45
|
-
_construct = function _construct(Parent, args, Class) {
|
|
46
|
-
var a = [null];
|
|
47
|
-
a.push.apply(a, args);
|
|
48
|
-
var Constructor = Function.bind.apply(Parent, a);
|
|
49
|
-
var instance = new Constructor();
|
|
50
|
-
if (Class) _setPrototypeOf(instance, Class.prototype);
|
|
51
|
-
return instance;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return _construct.apply(null, arguments);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function _slicedToArray(arr, i) {
|
|
59
|
-
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function _toConsumableArray(arr) {
|
|
63
|
-
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function _arrayWithoutHoles(arr) {
|
|
67
|
-
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function _arrayWithHoles(arr) {
|
|
71
|
-
if (Array.isArray(arr)) return arr;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function _iterableToArray(iter) {
|
|
75
|
-
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function _iterableToArrayLimit(arr, i) {
|
|
79
|
-
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
80
|
-
|
|
81
|
-
if (_i == null) return;
|
|
82
|
-
var _arr = [];
|
|
83
|
-
var _n = true;
|
|
84
|
-
var _d = false;
|
|
85
|
-
|
|
86
|
-
var _s, _e;
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
|
|
90
|
-
_arr.push(_s.value);
|
|
91
|
-
|
|
92
|
-
if (i && _arr.length === i) break;
|
|
93
|
-
}
|
|
94
|
-
} catch (err) {
|
|
95
|
-
_d = true;
|
|
96
|
-
_e = err;
|
|
97
|
-
} finally {
|
|
98
|
-
try {
|
|
99
|
-
if (!_n && _i["return"] != null) _i["return"]();
|
|
100
|
-
} finally {
|
|
101
|
-
if (_d) throw _e;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return _arr;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function _unsupportedIterableToArray(o, minLen) {
|
|
109
|
-
if (!o) return;
|
|
110
|
-
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
111
|
-
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
112
|
-
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
113
|
-
if (n === "Map" || n === "Set") return Array.from(o);
|
|
114
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function _arrayLikeToArray(arr, len) {
|
|
118
|
-
if (len == null || len > arr.length) len = arr.length;
|
|
119
|
-
|
|
120
|
-
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
121
|
-
|
|
122
|
-
return arr2;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function _nonIterableSpread() {
|
|
126
|
-
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function _nonIterableRest() {
|
|
130
|
-
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function _createForOfIteratorHelper(o, allowArrayLike) {
|
|
134
|
-
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
|
|
135
|
-
|
|
136
|
-
if (!it) {
|
|
137
|
-
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
|
|
138
|
-
if (it) o = it;
|
|
139
|
-
var i = 0;
|
|
140
|
-
|
|
141
|
-
var F = function () {};
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
s: F,
|
|
145
|
-
n: function () {
|
|
146
|
-
if (i >= o.length) return {
|
|
147
|
-
done: true
|
|
148
|
-
};
|
|
149
|
-
return {
|
|
150
|
-
done: false,
|
|
151
|
-
value: o[i++]
|
|
152
|
-
};
|
|
153
|
-
},
|
|
154
|
-
e: function (e) {
|
|
155
|
-
throw e;
|
|
156
|
-
},
|
|
157
|
-
f: F
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
var normalCompletion = true,
|
|
165
|
-
didErr = false,
|
|
166
|
-
err;
|
|
167
|
-
return {
|
|
168
|
-
s: function () {
|
|
169
|
-
it = it.call(o);
|
|
170
|
-
},
|
|
171
|
-
n: function () {
|
|
172
|
-
var step = it.next();
|
|
173
|
-
normalCompletion = step.done;
|
|
174
|
-
return step;
|
|
175
|
-
},
|
|
176
|
-
e: function (e) {
|
|
177
|
-
didErr = true;
|
|
178
|
-
err = e;
|
|
179
|
-
},
|
|
180
|
-
f: function () {
|
|
181
|
-
try {
|
|
182
|
-
if (!normalCompletion && it.return != null) it.return();
|
|
183
|
-
} finally {
|
|
184
|
-
if (didErr) throw err;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
var entries = Object.entries,
|
|
191
|
-
setPrototypeOf = Object.setPrototypeOf,
|
|
192
|
-
isFrozen = Object.isFrozen,
|
|
193
|
-
getPrototypeOf = Object.getPrototypeOf,
|
|
194
|
-
getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
195
|
-
var freeze = Object.freeze,
|
|
196
|
-
seal = Object.seal,
|
|
197
|
-
create = Object.create; // eslint-disable-line import/no-mutable-exports
|
|
198
|
-
|
|
199
|
-
var _ref = typeof Reflect !== 'undefined' && Reflect,
|
|
200
|
-
apply = _ref.apply,
|
|
201
|
-
construct = _ref.construct;
|
|
9
|
+
const {
|
|
10
|
+
entries,
|
|
11
|
+
setPrototypeOf,
|
|
12
|
+
isFrozen,
|
|
13
|
+
getPrototypeOf,
|
|
14
|
+
getOwnPropertyDescriptor
|
|
15
|
+
} = Object;
|
|
16
|
+
let {
|
|
17
|
+
freeze,
|
|
18
|
+
seal,
|
|
19
|
+
create
|
|
20
|
+
} = Object; // eslint-disable-line import/no-mutable-exports
|
|
21
|
+
|
|
22
|
+
let {
|
|
23
|
+
apply,
|
|
24
|
+
construct
|
|
25
|
+
} = typeof Reflect !== 'undefined' && Reflect;
|
|
202
26
|
|
|
203
27
|
if (!apply) {
|
|
204
28
|
apply = function apply(fun, thisValue, args) {
|
|
@@ -220,21 +44,21 @@
|
|
|
220
44
|
|
|
221
45
|
if (!construct) {
|
|
222
46
|
construct = function construct(Func, args) {
|
|
223
|
-
return
|
|
47
|
+
return new Func(...args);
|
|
224
48
|
};
|
|
225
49
|
}
|
|
226
50
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
51
|
+
const arrayForEach = unapply(Array.prototype.forEach);
|
|
52
|
+
const arrayPop = unapply(Array.prototype.pop);
|
|
53
|
+
const arrayPush = unapply(Array.prototype.push);
|
|
54
|
+
const stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
55
|
+
const stringToString = unapply(String.prototype.toString);
|
|
56
|
+
const stringMatch = unapply(String.prototype.match);
|
|
57
|
+
const stringReplace = unapply(String.prototype.replace);
|
|
58
|
+
const stringIndexOf = unapply(String.prototype.indexOf);
|
|
59
|
+
const stringTrim = unapply(String.prototype.trim);
|
|
60
|
+
const regExpTest = unapply(RegExp.prototype.test);
|
|
61
|
+
const typeErrorCreate = unconstruct(TypeError);
|
|
238
62
|
function unapply(func) {
|
|
239
63
|
return function (thisArg) {
|
|
240
64
|
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
@@ -265,13 +89,13 @@
|
|
|
265
89
|
setPrototypeOf(set, null);
|
|
266
90
|
}
|
|
267
91
|
|
|
268
|
-
|
|
92
|
+
let l = array.length;
|
|
269
93
|
|
|
270
94
|
while (l--) {
|
|
271
|
-
|
|
95
|
+
let element = array[l];
|
|
272
96
|
|
|
273
97
|
if (typeof element === 'string') {
|
|
274
|
-
|
|
98
|
+
const lcElement = transformCaseFunc(element);
|
|
275
99
|
|
|
276
100
|
if (lcElement !== element) {
|
|
277
101
|
// Config presets (e.g. tags.js, attrs.js) are immutable.
|
|
@@ -291,23 +115,10 @@
|
|
|
291
115
|
/* Shallow clone an object */
|
|
292
116
|
|
|
293
117
|
function clone(object) {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
var _iterator = _createForOfIteratorHelper(entries(object)),
|
|
297
|
-
_step;
|
|
118
|
+
const newObject = create(null);
|
|
298
119
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
var _step$value = _slicedToArray(_step.value, 2),
|
|
302
|
-
property = _step$value[0],
|
|
303
|
-
value = _step$value[1];
|
|
304
|
-
|
|
305
|
-
newObject[property] = value;
|
|
306
|
-
}
|
|
307
|
-
} catch (err) {
|
|
308
|
-
_iterator.e(err);
|
|
309
|
-
} finally {
|
|
310
|
-
_iterator.f();
|
|
120
|
+
for (const [property, value] of entries(object)) {
|
|
121
|
+
newObject[property] = value;
|
|
311
122
|
}
|
|
312
123
|
|
|
313
124
|
return newObject;
|
|
@@ -317,7 +128,7 @@
|
|
|
317
128
|
|
|
318
129
|
function lookupGetter(object, prop) {
|
|
319
130
|
while (object !== null) {
|
|
320
|
-
|
|
131
|
+
const desc = getOwnPropertyDescriptor(object, prop);
|
|
321
132
|
|
|
322
133
|
if (desc) {
|
|
323
134
|
if (desc.get) {
|
|
@@ -340,44 +151,55 @@
|
|
|
340
151
|
return fallbackValue;
|
|
341
152
|
}
|
|
342
153
|
|
|
343
|
-
|
|
154
|
+
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
|
|
344
155
|
|
|
345
|
-
|
|
346
|
-
|
|
156
|
+
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']);
|
|
157
|
+
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.
|
|
347
158
|
// We still need to know them so that we can do namespace
|
|
348
159
|
// checks properly in case one wants to add them to
|
|
349
160
|
// allow-list.
|
|
350
161
|
|
|
351
|
-
|
|
352
|
-
|
|
162
|
+
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']);
|
|
163
|
+
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,
|
|
353
164
|
// even those that we disallow by default.
|
|
354
165
|
|
|
355
|
-
|
|
356
|
-
|
|
166
|
+
const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
167
|
+
const text = freeze(['#text']);
|
|
357
168
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
169
|
+
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']);
|
|
170
|
+
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']);
|
|
171
|
+
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']);
|
|
172
|
+
const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
362
173
|
|
|
363
|
-
|
|
174
|
+
const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
|
|
364
175
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
176
|
+
const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
|
|
177
|
+
const TMPLIT_EXPR = seal(/\${[\w\W]*}/gm);
|
|
178
|
+
const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
|
|
368
179
|
|
|
369
|
-
|
|
180
|
+
const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
|
|
370
181
|
|
|
371
|
-
|
|
182
|
+
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
|
|
372
183
|
);
|
|
373
|
-
|
|
374
|
-
|
|
184
|
+
const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
|
|
185
|
+
const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
|
|
375
186
|
);
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
var
|
|
379
|
-
|
|
380
|
-
|
|
187
|
+
const DOCTYPE_NAME = seal(/^html$/i);
|
|
188
|
+
|
|
189
|
+
var EXPRESSIONS = /*#__PURE__*/Object.freeze({
|
|
190
|
+
__proto__: null,
|
|
191
|
+
MUSTACHE_EXPR: MUSTACHE_EXPR,
|
|
192
|
+
ERB_EXPR: ERB_EXPR,
|
|
193
|
+
TMPLIT_EXPR: TMPLIT_EXPR,
|
|
194
|
+
DATA_ATTR: DATA_ATTR,
|
|
195
|
+
ARIA_ATTR: ARIA_ATTR,
|
|
196
|
+
IS_ALLOWED_URI: IS_ALLOWED_URI,
|
|
197
|
+
IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
|
|
198
|
+
ATTR_WHITESPACE: ATTR_WHITESPACE,
|
|
199
|
+
DOCTYPE_NAME: DOCTYPE_NAME
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
const getGlobal = () => typeof window === 'undefined' ? null : window;
|
|
381
203
|
/**
|
|
382
204
|
* Creates a no-op policy for internal use only.
|
|
383
205
|
* Don't export this function outside this module!
|
|
@@ -388,31 +210,33 @@
|
|
|
388
210
|
*/
|
|
389
211
|
|
|
390
212
|
|
|
391
|
-
|
|
392
|
-
if (
|
|
213
|
+
const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
|
|
214
|
+
if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
|
|
393
215
|
return null;
|
|
394
216
|
} // Allow the callers to control the unique policy name
|
|
395
217
|
// by adding a data-tt-policy-suffix to the script element with the DOMPurify.
|
|
396
218
|
// Policy creation with duplicate names throws in Trusted Types.
|
|
397
219
|
|
|
398
220
|
|
|
399
|
-
|
|
400
|
-
|
|
221
|
+
let suffix = null;
|
|
222
|
+
const ATTR_NAME = 'data-tt-policy-suffix';
|
|
401
223
|
|
|
402
224
|
if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
|
|
403
225
|
suffix = document.currentScript.getAttribute(ATTR_NAME);
|
|
404
226
|
}
|
|
405
227
|
|
|
406
|
-
|
|
228
|
+
const policyName = 'dompurify' + (suffix ? '#' + suffix : '');
|
|
407
229
|
|
|
408
230
|
try {
|
|
409
231
|
return trustedTypes.createPolicy(policyName, {
|
|
410
|
-
createHTML
|
|
232
|
+
createHTML(html) {
|
|
411
233
|
return html;
|
|
412
234
|
},
|
|
413
|
-
|
|
235
|
+
|
|
236
|
+
createScriptURL(scriptUrl) {
|
|
414
237
|
return scriptUrl;
|
|
415
238
|
}
|
|
239
|
+
|
|
416
240
|
});
|
|
417
241
|
} catch (_) {
|
|
418
242
|
// Policy creation failed (most likely another DOMPurify script has
|
|
@@ -424,18 +248,16 @@
|
|
|
424
248
|
};
|
|
425
249
|
|
|
426
250
|
function createDOMPurify() {
|
|
427
|
-
|
|
251
|
+
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
428
252
|
|
|
429
|
-
|
|
430
|
-
return createDOMPurify(root);
|
|
431
|
-
};
|
|
253
|
+
const DOMPurify = root => createDOMPurify(root);
|
|
432
254
|
/**
|
|
433
255
|
* Version label, exposed for easier checks
|
|
434
256
|
* if DOMPurify is up to date or not
|
|
435
257
|
*/
|
|
436
258
|
|
|
437
259
|
|
|
438
|
-
DOMPurify.version = '3.0.
|
|
260
|
+
DOMPurify.version = '3.0.2';
|
|
439
261
|
/**
|
|
440
262
|
* Array of elements that DOMPurify removed during sanitation.
|
|
441
263
|
* Empty if nothing was removed.
|
|
@@ -450,23 +272,26 @@
|
|
|
450
272
|
return DOMPurify;
|
|
451
273
|
}
|
|
452
274
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
275
|
+
const originalDocument = window.document;
|
|
276
|
+
let {
|
|
277
|
+
document
|
|
278
|
+
} = window;
|
|
279
|
+
const {
|
|
280
|
+
DocumentFragment,
|
|
281
|
+
HTMLTemplateElement,
|
|
282
|
+
Node,
|
|
283
|
+
Element,
|
|
284
|
+
NodeFilter,
|
|
285
|
+
NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,
|
|
286
|
+
HTMLFormElement,
|
|
287
|
+
DOMParser,
|
|
288
|
+
trustedTypes
|
|
289
|
+
} = window;
|
|
290
|
+
const ElementPrototype = Element.prototype;
|
|
291
|
+
const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
|
|
292
|
+
const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
|
|
293
|
+
const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
|
|
294
|
+
const getParentNode = lookupGetter(ElementPrototype, 'parentNode'); // As per issue #47, the web-components registry is inherited by a
|
|
470
295
|
// new document created via createHTMLDocument. As per the spec
|
|
471
296
|
// (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
|
|
472
297
|
// a new empty registry is used when creating a template contents owner
|
|
@@ -474,36 +299,43 @@
|
|
|
474
299
|
// is inherited.
|
|
475
300
|
|
|
476
301
|
if (typeof HTMLTemplateElement === 'function') {
|
|
477
|
-
|
|
302
|
+
const template = document.createElement('template');
|
|
478
303
|
|
|
479
304
|
if (template.content && template.content.ownerDocument) {
|
|
480
305
|
document = template.content.ownerDocument;
|
|
481
306
|
}
|
|
482
307
|
}
|
|
483
308
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
309
|
+
const trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
|
|
310
|
+
|
|
311
|
+
const emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
|
|
312
|
+
const {
|
|
313
|
+
implementation,
|
|
314
|
+
createNodeIterator,
|
|
315
|
+
createDocumentFragment,
|
|
316
|
+
getElementsByTagName
|
|
317
|
+
} = document;
|
|
318
|
+
const {
|
|
319
|
+
importNode
|
|
320
|
+
} = originalDocument;
|
|
321
|
+
let hooks = {};
|
|
494
322
|
/**
|
|
495
323
|
* Expose whether this browser supports running the full DOMPurify.
|
|
496
324
|
*/
|
|
497
325
|
|
|
498
326
|
DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined';
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
327
|
+
const {
|
|
328
|
+
MUSTACHE_EXPR,
|
|
329
|
+
ERB_EXPR,
|
|
330
|
+
TMPLIT_EXPR,
|
|
331
|
+
DATA_ATTR,
|
|
332
|
+
ARIA_ATTR,
|
|
333
|
+
IS_SCRIPT_OR_DATA,
|
|
334
|
+
ATTR_WHITESPACE
|
|
335
|
+
} = EXPRESSIONS;
|
|
336
|
+
let {
|
|
337
|
+
IS_ALLOWED_URI: IS_ALLOWED_URI$1
|
|
338
|
+
} = EXPRESSIONS;
|
|
507
339
|
/**
|
|
508
340
|
* We consider the elements and attributes below to be safe. Ideally
|
|
509
341
|
* don't add any new ones but feel free to remove unwanted ones.
|
|
@@ -511,12 +343,12 @@
|
|
|
511
343
|
|
|
512
344
|
/* allowed element names */
|
|
513
345
|
|
|
514
|
-
|
|
515
|
-
|
|
346
|
+
let ALLOWED_TAGS = null;
|
|
347
|
+
const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);
|
|
516
348
|
/* Allowed attribute names */
|
|
517
349
|
|
|
518
|
-
|
|
519
|
-
|
|
350
|
+
let ALLOWED_ATTR = null;
|
|
351
|
+
const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);
|
|
520
352
|
/*
|
|
521
353
|
* Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.
|
|
522
354
|
* @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
|
|
@@ -524,7 +356,7 @@
|
|
|
524
356
|
* @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
|
|
525
357
|
*/
|
|
526
358
|
|
|
527
|
-
|
|
359
|
+
let CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
|
|
528
360
|
tagNameCheck: {
|
|
529
361
|
writable: true,
|
|
530
362
|
configurable: false,
|
|
@@ -546,57 +378,57 @@
|
|
|
546
378
|
}));
|
|
547
379
|
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
|
|
548
380
|
|
|
549
|
-
|
|
381
|
+
let FORBID_TAGS = null;
|
|
550
382
|
/* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
|
|
551
383
|
|
|
552
|
-
|
|
384
|
+
let FORBID_ATTR = null;
|
|
553
385
|
/* Decide if ARIA attributes are okay */
|
|
554
386
|
|
|
555
|
-
|
|
387
|
+
let ALLOW_ARIA_ATTR = true;
|
|
556
388
|
/* Decide if custom data attributes are okay */
|
|
557
389
|
|
|
558
|
-
|
|
390
|
+
let ALLOW_DATA_ATTR = true;
|
|
559
391
|
/* Decide if unknown protocols are okay */
|
|
560
392
|
|
|
561
|
-
|
|
393
|
+
let ALLOW_UNKNOWN_PROTOCOLS = false;
|
|
562
394
|
/* Decide if self-closing tags in attributes are allowed.
|
|
563
395
|
* Usually removed due to a mXSS issue in jQuery 3.0 */
|
|
564
396
|
|
|
565
|
-
|
|
397
|
+
let ALLOW_SELF_CLOSE_IN_ATTR = true;
|
|
566
398
|
/* Output should be safe for common template engines.
|
|
567
399
|
* This means, DOMPurify removes data attributes, mustaches and ERB
|
|
568
400
|
*/
|
|
569
401
|
|
|
570
|
-
|
|
402
|
+
let SAFE_FOR_TEMPLATES = false;
|
|
571
403
|
/* Decide if document with <html>... should be returned */
|
|
572
404
|
|
|
573
|
-
|
|
405
|
+
let WHOLE_DOCUMENT = false;
|
|
574
406
|
/* Track whether config is already set on this instance of DOMPurify. */
|
|
575
407
|
|
|
576
|
-
|
|
408
|
+
let SET_CONFIG = false;
|
|
577
409
|
/* Decide if all elements (e.g. style, script) must be children of
|
|
578
410
|
* document.body. By default, browsers might move them to document.head */
|
|
579
411
|
|
|
580
|
-
|
|
412
|
+
let FORCE_BODY = false;
|
|
581
413
|
/* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
|
|
582
414
|
* string (or a TrustedHTML object if Trusted Types are supported).
|
|
583
415
|
* If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
|
|
584
416
|
*/
|
|
585
417
|
|
|
586
|
-
|
|
418
|
+
let RETURN_DOM = false;
|
|
587
419
|
/* Decide if a DOM `DocumentFragment` should be returned, instead of a html
|
|
588
420
|
* string (or a TrustedHTML object if Trusted Types are supported) */
|
|
589
421
|
|
|
590
|
-
|
|
422
|
+
let RETURN_DOM_FRAGMENT = false;
|
|
591
423
|
/* Try to return a Trusted Type object instead of a string, return a string in
|
|
592
424
|
* case Trusted Types are not supported */
|
|
593
425
|
|
|
594
|
-
|
|
426
|
+
let RETURN_TRUSTED_TYPE = false;
|
|
595
427
|
/* Output should be free from DOM clobbering attacks?
|
|
596
428
|
* This sanitizes markups named with colliding, clobberable built-in DOM APIs.
|
|
597
429
|
*/
|
|
598
430
|
|
|
599
|
-
|
|
431
|
+
let SANITIZE_DOM = true;
|
|
600
432
|
/* Achieve full DOM Clobbering protection by isolating the namespace of named
|
|
601
433
|
* properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.
|
|
602
434
|
*
|
|
@@ -611,57 +443,57 @@
|
|
|
611
443
|
* with a constant string, i.e., `user-content-`
|
|
612
444
|
*/
|
|
613
445
|
|
|
614
|
-
|
|
615
|
-
|
|
446
|
+
let SANITIZE_NAMED_PROPS = false;
|
|
447
|
+
const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';
|
|
616
448
|
/* Keep element content when removing element? */
|
|
617
449
|
|
|
618
|
-
|
|
450
|
+
let KEEP_CONTENT = true;
|
|
619
451
|
/* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
|
|
620
452
|
* of importing it into a new Document and returning a sanitized copy */
|
|
621
453
|
|
|
622
|
-
|
|
454
|
+
let IN_PLACE = false;
|
|
623
455
|
/* Allow usage of profiles like html, svg and mathMl */
|
|
624
456
|
|
|
625
|
-
|
|
457
|
+
let USE_PROFILES = {};
|
|
626
458
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
627
459
|
|
|
628
|
-
|
|
629
|
-
|
|
460
|
+
let FORBID_CONTENTS = null;
|
|
461
|
+
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']);
|
|
630
462
|
/* Tags that are safe for data: URIs */
|
|
631
463
|
|
|
632
|
-
|
|
633
|
-
|
|
464
|
+
let DATA_URI_TAGS = null;
|
|
465
|
+
const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);
|
|
634
466
|
/* Attributes safe for values like "javascript:" */
|
|
635
467
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
468
|
+
let URI_SAFE_ATTRIBUTES = null;
|
|
469
|
+
const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
|
|
470
|
+
const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
|
|
471
|
+
const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
472
|
+
const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
|
|
641
473
|
/* Document namespace */
|
|
642
474
|
|
|
643
|
-
|
|
644
|
-
|
|
475
|
+
let NAMESPACE = HTML_NAMESPACE;
|
|
476
|
+
let IS_EMPTY_INPUT = false;
|
|
645
477
|
/* Allowed XHTML+XML namespaces */
|
|
646
478
|
|
|
647
|
-
|
|
648
|
-
|
|
479
|
+
let ALLOWED_NAMESPACES = null;
|
|
480
|
+
const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
|
|
649
481
|
/* Parsing of strict XHTML documents */
|
|
650
482
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
483
|
+
let PARSER_MEDIA_TYPE;
|
|
484
|
+
const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
|
|
485
|
+
const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
|
|
486
|
+
let transformCaseFunc;
|
|
655
487
|
/* Keep a reference to config to pass to hooks */
|
|
656
488
|
|
|
657
|
-
|
|
489
|
+
let CONFIG = null;
|
|
658
490
|
/* Ideally, do not touch anything below this line */
|
|
659
491
|
|
|
660
492
|
/* ______________________________________________ */
|
|
661
493
|
|
|
662
|
-
|
|
494
|
+
const formElement = document.createElement('form');
|
|
663
495
|
|
|
664
|
-
|
|
496
|
+
const isRegexOrFunction = function isRegexOrFunction(testValue) {
|
|
665
497
|
return testValue instanceof RegExp || testValue instanceof Function;
|
|
666
498
|
};
|
|
667
499
|
/**
|
|
@@ -672,14 +504,14 @@
|
|
|
672
504
|
// eslint-disable-next-line complexity
|
|
673
505
|
|
|
674
506
|
|
|
675
|
-
|
|
507
|
+
const _parseConfig = function _parseConfig(cfg) {
|
|
676
508
|
if (CONFIG && CONFIG === cfg) {
|
|
677
509
|
return;
|
|
678
510
|
}
|
|
679
511
|
/* Shield configuration object from tampering */
|
|
680
512
|
|
|
681
513
|
|
|
682
|
-
if (!cfg ||
|
|
514
|
+
if (!cfg || typeof cfg !== 'object') {
|
|
683
515
|
cfg = {};
|
|
684
516
|
}
|
|
685
517
|
/* Shield configuration object from prototype pollution */
|
|
@@ -737,8 +569,9 @@
|
|
|
737
569
|
|
|
738
570
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
739
571
|
|
|
740
|
-
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI
|
|
572
|
+
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;
|
|
741
573
|
NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
|
|
574
|
+
CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
|
|
742
575
|
|
|
743
576
|
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
|
|
744
577
|
CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
|
|
@@ -763,7 +596,7 @@
|
|
|
763
596
|
|
|
764
597
|
|
|
765
598
|
if (USE_PROFILES) {
|
|
766
|
-
ALLOWED_TAGS = addToSet({},
|
|
599
|
+
ALLOWED_TAGS = addToSet({}, [...text]);
|
|
767
600
|
ALLOWED_ATTR = [];
|
|
768
601
|
|
|
769
602
|
if (USE_PROFILES.html === true) {
|
|
@@ -848,21 +681,21 @@
|
|
|
848
681
|
CONFIG = cfg;
|
|
849
682
|
};
|
|
850
683
|
|
|
851
|
-
|
|
852
|
-
|
|
684
|
+
const MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
|
|
685
|
+
const HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']); // Certain elements are allowed in both SVG and HTML
|
|
853
686
|
// namespace. We need to specify them explicitly
|
|
854
687
|
// so that they don't get erroneously deleted from
|
|
855
688
|
// HTML namespace.
|
|
856
689
|
|
|
857
|
-
|
|
690
|
+
const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
|
|
858
691
|
/* Keep track of all possible SVG and MathML tags
|
|
859
692
|
* so that we can perform the namespace checks
|
|
860
693
|
* correctly. */
|
|
861
694
|
|
|
862
|
-
|
|
695
|
+
const ALL_SVG_TAGS = addToSet({}, svg$1);
|
|
863
696
|
addToSet(ALL_SVG_TAGS, svgFilters);
|
|
864
697
|
addToSet(ALL_SVG_TAGS, svgDisallowed);
|
|
865
|
-
|
|
698
|
+
const ALL_MATHML_TAGS = addToSet({}, mathMl$1);
|
|
866
699
|
addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
|
|
867
700
|
/**
|
|
868
701
|
*
|
|
@@ -873,8 +706,8 @@
|
|
|
873
706
|
* return. Return true otherwise.
|
|
874
707
|
*/
|
|
875
708
|
|
|
876
|
-
|
|
877
|
-
|
|
709
|
+
const _checkValidNamespace = function _checkValidNamespace(element) {
|
|
710
|
+
let parent = getParentNode(element); // In JSDOM, if we're inside shadow DOM, then parentNode
|
|
878
711
|
// can be null. We just simulate parent in this case.
|
|
879
712
|
|
|
880
713
|
if (!parent || !parent.tagName) {
|
|
@@ -884,8 +717,8 @@
|
|
|
884
717
|
};
|
|
885
718
|
}
|
|
886
719
|
|
|
887
|
-
|
|
888
|
-
|
|
720
|
+
const tagName = stringToLowerCase(element.tagName);
|
|
721
|
+
const parentTagName = stringToLowerCase(parent.tagName);
|
|
889
722
|
|
|
890
723
|
if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
|
|
891
724
|
return false;
|
|
@@ -965,7 +798,7 @@
|
|
|
965
798
|
*/
|
|
966
799
|
|
|
967
800
|
|
|
968
|
-
|
|
801
|
+
const _forceRemove = function _forceRemove(node) {
|
|
969
802
|
arrayPush(DOMPurify.removed, {
|
|
970
803
|
element: node
|
|
971
804
|
});
|
|
@@ -985,7 +818,7 @@
|
|
|
985
818
|
*/
|
|
986
819
|
|
|
987
820
|
|
|
988
|
-
|
|
821
|
+
const _removeAttribute = function _removeAttribute(name, node) {
|
|
989
822
|
try {
|
|
990
823
|
arrayPush(DOMPurify.removed, {
|
|
991
824
|
attribute: node.getAttributeNode(name),
|
|
@@ -1020,16 +853,16 @@
|
|
|
1020
853
|
*/
|
|
1021
854
|
|
|
1022
855
|
|
|
1023
|
-
|
|
856
|
+
const _initDocument = function _initDocument(dirty) {
|
|
1024
857
|
/* Create a HTML document */
|
|
1025
|
-
|
|
1026
|
-
|
|
858
|
+
let doc;
|
|
859
|
+
let leadingWhitespace;
|
|
1027
860
|
|
|
1028
861
|
if (FORCE_BODY) {
|
|
1029
862
|
dirty = '<remove></remove>' + dirty;
|
|
1030
863
|
} else {
|
|
1031
864
|
/* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
|
|
1032
|
-
|
|
865
|
+
const matches = stringMatch(dirty, /^[\r\n\t ]+/);
|
|
1033
866
|
leadingWhitespace = matches && matches[0];
|
|
1034
867
|
}
|
|
1035
868
|
|
|
@@ -1038,7 +871,7 @@
|
|
|
1038
871
|
dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
|
|
1039
872
|
}
|
|
1040
873
|
|
|
1041
|
-
|
|
874
|
+
const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
1042
875
|
/*
|
|
1043
876
|
* Use the DOMParser API by default, fallback later if needs be
|
|
1044
877
|
* DOMParser not work for svg when has multiple root element.
|
|
@@ -1061,7 +894,7 @@
|
|
|
1061
894
|
}
|
|
1062
895
|
}
|
|
1063
896
|
|
|
1064
|
-
|
|
897
|
+
const body = doc.body || doc.documentElement;
|
|
1065
898
|
|
|
1066
899
|
if (dirty && leadingWhitespace) {
|
|
1067
900
|
body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
|
|
@@ -1083,7 +916,7 @@
|
|
|
1083
916
|
*/
|
|
1084
917
|
|
|
1085
918
|
|
|
1086
|
-
|
|
919
|
+
const _createIterator = function _createIterator(root) {
|
|
1087
920
|
return createNodeIterator.call(root.ownerDocument || root, root, // eslint-disable-next-line no-bitwise
|
|
1088
921
|
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
|
|
1089
922
|
};
|
|
@@ -1095,7 +928,7 @@
|
|
|
1095
928
|
*/
|
|
1096
929
|
|
|
1097
930
|
|
|
1098
|
-
|
|
931
|
+
const _isClobbered = function _isClobbered(elm) {
|
|
1099
932
|
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');
|
|
1100
933
|
};
|
|
1101
934
|
/**
|
|
@@ -1106,8 +939,8 @@
|
|
|
1106
939
|
*/
|
|
1107
940
|
|
|
1108
941
|
|
|
1109
|
-
|
|
1110
|
-
return
|
|
942
|
+
const _isNode = function _isNode(object) {
|
|
943
|
+
return typeof Node === 'object' ? object instanceof Node : object && typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
|
|
1111
944
|
};
|
|
1112
945
|
/**
|
|
1113
946
|
* _executeHook
|
|
@@ -1119,12 +952,12 @@
|
|
|
1119
952
|
*/
|
|
1120
953
|
|
|
1121
954
|
|
|
1122
|
-
|
|
955
|
+
const _executeHook = function _executeHook(entryPoint, currentNode, data) {
|
|
1123
956
|
if (!hooks[entryPoint]) {
|
|
1124
957
|
return;
|
|
1125
958
|
}
|
|
1126
959
|
|
|
1127
|
-
arrayForEach(hooks[entryPoint],
|
|
960
|
+
arrayForEach(hooks[entryPoint], hook => {
|
|
1128
961
|
hook.call(DOMPurify, currentNode, data, CONFIG);
|
|
1129
962
|
});
|
|
1130
963
|
};
|
|
@@ -1140,8 +973,8 @@
|
|
|
1140
973
|
*/
|
|
1141
974
|
|
|
1142
975
|
|
|
1143
|
-
|
|
1144
|
-
|
|
976
|
+
const _sanitizeElements = function _sanitizeElements(currentNode) {
|
|
977
|
+
let content;
|
|
1145
978
|
/* Execute a hook if present */
|
|
1146
979
|
|
|
1147
980
|
_executeHook('beforeSanitizeElements', currentNode, null);
|
|
@@ -1156,11 +989,11 @@
|
|
|
1156
989
|
/* Now let's check the element's type and name */
|
|
1157
990
|
|
|
1158
991
|
|
|
1159
|
-
|
|
992
|
+
const tagName = transformCaseFunc(currentNode.nodeName);
|
|
1160
993
|
/* Execute a hook if present */
|
|
1161
994
|
|
|
1162
995
|
_executeHook('uponSanitizeElement', currentNode, {
|
|
1163
|
-
tagName
|
|
996
|
+
tagName,
|
|
1164
997
|
allowedTags: ALLOWED_TAGS
|
|
1165
998
|
});
|
|
1166
999
|
/* Detect mXSS attempts abusing namespace confusion */
|
|
@@ -1184,13 +1017,13 @@
|
|
|
1184
1017
|
|
|
1185
1018
|
|
|
1186
1019
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
1187
|
-
|
|
1188
|
-
|
|
1020
|
+
const parentNode = getParentNode(currentNode) || currentNode.parentNode;
|
|
1021
|
+
const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
|
|
1189
1022
|
|
|
1190
1023
|
if (childNodes && parentNode) {
|
|
1191
|
-
|
|
1024
|
+
const childCount = childNodes.length;
|
|
1192
1025
|
|
|
1193
|
-
for (
|
|
1026
|
+
for (let i = childCount - 1; i >= 0; --i) {
|
|
1194
1027
|
parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
|
|
1195
1028
|
}
|
|
1196
1029
|
}
|
|
@@ -1222,9 +1055,9 @@
|
|
|
1222
1055
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
|
1223
1056
|
/* Get the element's text content */
|
|
1224
1057
|
content = currentNode.textContent;
|
|
1225
|
-
content = stringReplace(content, MUSTACHE_EXPR
|
|
1226
|
-
content = stringReplace(content, ERB_EXPR
|
|
1227
|
-
content = stringReplace(content, TMPLIT_EXPR
|
|
1058
|
+
content = stringReplace(content, MUSTACHE_EXPR, ' ');
|
|
1059
|
+
content = stringReplace(content, ERB_EXPR, ' ');
|
|
1060
|
+
content = stringReplace(content, TMPLIT_EXPR, ' ');
|
|
1228
1061
|
|
|
1229
1062
|
if (currentNode.textContent !== content) {
|
|
1230
1063
|
arrayPush(DOMPurify.removed, {
|
|
@@ -1251,7 +1084,7 @@
|
|
|
1251
1084
|
// eslint-disable-next-line complexity
|
|
1252
1085
|
|
|
1253
1086
|
|
|
1254
|
-
|
|
1087
|
+
const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
1255
1088
|
/* Make sure attribute cannot clobber */
|
|
1256
1089
|
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
1257
1090
|
return false;
|
|
@@ -1262,7 +1095,7 @@
|
|
|
1262
1095
|
We don't need to check the value; it's always URI safe. */
|
|
1263
1096
|
|
|
1264
1097
|
|
|
1265
|
-
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR
|
|
1098
|
+
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]) {
|
|
1266
1099
|
if ( // First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
1267
1100
|
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1268
1101
|
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
|
|
@@ -1273,7 +1106,7 @@
|
|
|
1273
1106
|
}
|
|
1274
1107
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
1275
1108
|
|
|
1276
|
-
} else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE
|
|
1109
|
+
} 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 {
|
|
1277
1110
|
return false;
|
|
1278
1111
|
}
|
|
1279
1112
|
|
|
@@ -1287,7 +1120,7 @@
|
|
|
1287
1120
|
*/
|
|
1288
1121
|
|
|
1289
1122
|
|
|
1290
|
-
|
|
1123
|
+
const _basicCustomElementTest = function _basicCustomElementTest(tagName) {
|
|
1291
1124
|
return tagName.indexOf('-') > 0;
|
|
1292
1125
|
};
|
|
1293
1126
|
/**
|
|
@@ -1302,23 +1135,25 @@
|
|
|
1302
1135
|
*/
|
|
1303
1136
|
|
|
1304
1137
|
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1138
|
+
const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
1139
|
+
let attr;
|
|
1140
|
+
let value;
|
|
1141
|
+
let lcName;
|
|
1142
|
+
let l;
|
|
1310
1143
|
/* Execute a hook if present */
|
|
1311
1144
|
|
|
1312
1145
|
_executeHook('beforeSanitizeAttributes', currentNode, null);
|
|
1313
1146
|
|
|
1314
|
-
|
|
1147
|
+
const {
|
|
1148
|
+
attributes
|
|
1149
|
+
} = currentNode;
|
|
1315
1150
|
/* Check if we have attributes; if not we might have a text node */
|
|
1316
1151
|
|
|
1317
1152
|
if (!attributes) {
|
|
1318
1153
|
return;
|
|
1319
1154
|
}
|
|
1320
1155
|
|
|
1321
|
-
|
|
1156
|
+
const hookEvent = {
|
|
1322
1157
|
attrName: '',
|
|
1323
1158
|
attrValue: '',
|
|
1324
1159
|
keepAttr: true,
|
|
@@ -1329,9 +1164,10 @@
|
|
|
1329
1164
|
|
|
1330
1165
|
while (l--) {
|
|
1331
1166
|
attr = attributes[l];
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1167
|
+
const {
|
|
1168
|
+
name,
|
|
1169
|
+
namespaceURI
|
|
1170
|
+
} = attr;
|
|
1335
1171
|
value = name === 'value' ? attr.value : stringTrim(attr.value);
|
|
1336
1172
|
lcName = transformCaseFunc(name);
|
|
1337
1173
|
/* Execute a hook if present */
|
|
@@ -1371,14 +1207,14 @@
|
|
|
1371
1207
|
|
|
1372
1208
|
|
|
1373
1209
|
if (SAFE_FOR_TEMPLATES) {
|
|
1374
|
-
value = stringReplace(value, MUSTACHE_EXPR
|
|
1375
|
-
value = stringReplace(value, ERB_EXPR
|
|
1376
|
-
value = stringReplace(value, TMPLIT_EXPR
|
|
1210
|
+
value = stringReplace(value, MUSTACHE_EXPR, ' ');
|
|
1211
|
+
value = stringReplace(value, ERB_EXPR, ' ');
|
|
1212
|
+
value = stringReplace(value, TMPLIT_EXPR, ' ');
|
|
1377
1213
|
}
|
|
1378
1214
|
/* Is `value` valid for this attribute? */
|
|
1379
1215
|
|
|
1380
1216
|
|
|
1381
|
-
|
|
1217
|
+
const lcTag = transformCaseFunc(currentNode.nodeName);
|
|
1382
1218
|
|
|
1383
1219
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
1384
1220
|
continue;
|
|
@@ -1398,7 +1234,7 @@
|
|
|
1398
1234
|
/* Handle attributes that require Trusted Types */
|
|
1399
1235
|
|
|
1400
1236
|
|
|
1401
|
-
if (trustedTypesPolicy &&
|
|
1237
|
+
if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {
|
|
1402
1238
|
if (namespaceURI) ; else {
|
|
1403
1239
|
switch (trustedTypes.getAttributeType(lcTag, lcName)) {
|
|
1404
1240
|
case 'TrustedHTML':
|
|
@@ -1437,10 +1273,10 @@
|
|
|
1437
1273
|
*/
|
|
1438
1274
|
|
|
1439
1275
|
|
|
1440
|
-
|
|
1441
|
-
|
|
1276
|
+
const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
|
|
1277
|
+
let shadowNode;
|
|
1442
1278
|
|
|
1443
|
-
|
|
1279
|
+
const shadowIterator = _createIterator(fragment);
|
|
1444
1280
|
/* Execute a hook if present */
|
|
1445
1281
|
|
|
1446
1282
|
|
|
@@ -1482,11 +1318,11 @@
|
|
|
1482
1318
|
|
|
1483
1319
|
|
|
1484
1320
|
DOMPurify.sanitize = function (dirty) {
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1321
|
+
let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
1322
|
+
let body;
|
|
1323
|
+
let importedNode;
|
|
1324
|
+
let currentNode;
|
|
1325
|
+
let returnNode;
|
|
1490
1326
|
/* Make sure we have a string to sanitize.
|
|
1491
1327
|
DO NOT return early, as this will return the wrong type if
|
|
1492
1328
|
the user has requested a DOM object rather than a string */
|
|
@@ -1536,7 +1372,7 @@
|
|
|
1536
1372
|
if (IN_PLACE) {
|
|
1537
1373
|
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
1538
1374
|
if (dirty.nodeName) {
|
|
1539
|
-
|
|
1375
|
+
const tagName = transformCaseFunc(dirty.nodeName);
|
|
1540
1376
|
|
|
1541
1377
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
1542
1378
|
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
@@ -1582,7 +1418,7 @@
|
|
|
1582
1418
|
/* Get node iterator */
|
|
1583
1419
|
|
|
1584
1420
|
|
|
1585
|
-
|
|
1421
|
+
const nodeIterator = _createIterator(IN_PLACE ? dirty : body);
|
|
1586
1422
|
/* Now start iterating over the created document */
|
|
1587
1423
|
|
|
1588
1424
|
|
|
@@ -1637,7 +1473,7 @@
|
|
|
1637
1473
|
return returnNode;
|
|
1638
1474
|
}
|
|
1639
1475
|
|
|
1640
|
-
|
|
1476
|
+
let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
|
1641
1477
|
/* Serialize doctype if allowed */
|
|
1642
1478
|
|
|
1643
1479
|
if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
|
|
@@ -1647,9 +1483,9 @@
|
|
|
1647
1483
|
|
|
1648
1484
|
|
|
1649
1485
|
if (SAFE_FOR_TEMPLATES) {
|
|
1650
|
-
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR
|
|
1651
|
-
serializedHTML = stringReplace(serializedHTML, ERB_EXPR
|
|
1652
|
-
serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR
|
|
1486
|
+
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR, ' ');
|
|
1487
|
+
serializedHTML = stringReplace(serializedHTML, ERB_EXPR, ' ');
|
|
1488
|
+
serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR, ' ');
|
|
1653
1489
|
}
|
|
1654
1490
|
|
|
1655
1491
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
|
@@ -1696,8 +1532,8 @@
|
|
|
1696
1532
|
_parseConfig({});
|
|
1697
1533
|
}
|
|
1698
1534
|
|
|
1699
|
-
|
|
1700
|
-
|
|
1535
|
+
const lcTag = transformCaseFunc(tag);
|
|
1536
|
+
const lcName = transformCaseFunc(attr);
|
|
1701
1537
|
return _isValidAttribute(lcTag, lcName, value);
|
|
1702
1538
|
};
|
|
1703
1539
|
/**
|