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.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,7 +569,7 @@
|
|
|
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;
|
|
742
574
|
CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
|
|
743
575
|
|
|
@@ -764,7 +596,7 @@
|
|
|
764
596
|
|
|
765
597
|
|
|
766
598
|
if (USE_PROFILES) {
|
|
767
|
-
ALLOWED_TAGS = addToSet({},
|
|
599
|
+
ALLOWED_TAGS = addToSet({}, [...text]);
|
|
768
600
|
ALLOWED_ATTR = [];
|
|
769
601
|
|
|
770
602
|
if (USE_PROFILES.html === true) {
|
|
@@ -849,21 +681,21 @@
|
|
|
849
681
|
CONFIG = cfg;
|
|
850
682
|
};
|
|
851
683
|
|
|
852
|
-
|
|
853
|
-
|
|
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
|
|
854
686
|
// namespace. We need to specify them explicitly
|
|
855
687
|
// so that they don't get erroneously deleted from
|
|
856
688
|
// HTML namespace.
|
|
857
689
|
|
|
858
|
-
|
|
690
|
+
const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
|
|
859
691
|
/* Keep track of all possible SVG and MathML tags
|
|
860
692
|
* so that we can perform the namespace checks
|
|
861
693
|
* correctly. */
|
|
862
694
|
|
|
863
|
-
|
|
695
|
+
const ALL_SVG_TAGS = addToSet({}, svg$1);
|
|
864
696
|
addToSet(ALL_SVG_TAGS, svgFilters);
|
|
865
697
|
addToSet(ALL_SVG_TAGS, svgDisallowed);
|
|
866
|
-
|
|
698
|
+
const ALL_MATHML_TAGS = addToSet({}, mathMl$1);
|
|
867
699
|
addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
|
|
868
700
|
/**
|
|
869
701
|
*
|
|
@@ -874,8 +706,8 @@
|
|
|
874
706
|
* return. Return true otherwise.
|
|
875
707
|
*/
|
|
876
708
|
|
|
877
|
-
|
|
878
|
-
|
|
709
|
+
const _checkValidNamespace = function _checkValidNamespace(element) {
|
|
710
|
+
let parent = getParentNode(element); // In JSDOM, if we're inside shadow DOM, then parentNode
|
|
879
711
|
// can be null. We just simulate parent in this case.
|
|
880
712
|
|
|
881
713
|
if (!parent || !parent.tagName) {
|
|
@@ -885,8 +717,8 @@
|
|
|
885
717
|
};
|
|
886
718
|
}
|
|
887
719
|
|
|
888
|
-
|
|
889
|
-
|
|
720
|
+
const tagName = stringToLowerCase(element.tagName);
|
|
721
|
+
const parentTagName = stringToLowerCase(parent.tagName);
|
|
890
722
|
|
|
891
723
|
if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
|
|
892
724
|
return false;
|
|
@@ -966,7 +798,7 @@
|
|
|
966
798
|
*/
|
|
967
799
|
|
|
968
800
|
|
|
969
|
-
|
|
801
|
+
const _forceRemove = function _forceRemove(node) {
|
|
970
802
|
arrayPush(DOMPurify.removed, {
|
|
971
803
|
element: node
|
|
972
804
|
});
|
|
@@ -986,7 +818,7 @@
|
|
|
986
818
|
*/
|
|
987
819
|
|
|
988
820
|
|
|
989
|
-
|
|
821
|
+
const _removeAttribute = function _removeAttribute(name, node) {
|
|
990
822
|
try {
|
|
991
823
|
arrayPush(DOMPurify.removed, {
|
|
992
824
|
attribute: node.getAttributeNode(name),
|
|
@@ -1021,16 +853,16 @@
|
|
|
1021
853
|
*/
|
|
1022
854
|
|
|
1023
855
|
|
|
1024
|
-
|
|
856
|
+
const _initDocument = function _initDocument(dirty) {
|
|
1025
857
|
/* Create a HTML document */
|
|
1026
|
-
|
|
1027
|
-
|
|
858
|
+
let doc;
|
|
859
|
+
let leadingWhitespace;
|
|
1028
860
|
|
|
1029
861
|
if (FORCE_BODY) {
|
|
1030
862
|
dirty = '<remove></remove>' + dirty;
|
|
1031
863
|
} else {
|
|
1032
864
|
/* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
|
|
1033
|
-
|
|
865
|
+
const matches = stringMatch(dirty, /^[\r\n\t ]+/);
|
|
1034
866
|
leadingWhitespace = matches && matches[0];
|
|
1035
867
|
}
|
|
1036
868
|
|
|
@@ -1039,7 +871,7 @@
|
|
|
1039
871
|
dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
|
|
1040
872
|
}
|
|
1041
873
|
|
|
1042
|
-
|
|
874
|
+
const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
1043
875
|
/*
|
|
1044
876
|
* Use the DOMParser API by default, fallback later if needs be
|
|
1045
877
|
* DOMParser not work for svg when has multiple root element.
|
|
@@ -1062,7 +894,7 @@
|
|
|
1062
894
|
}
|
|
1063
895
|
}
|
|
1064
896
|
|
|
1065
|
-
|
|
897
|
+
const body = doc.body || doc.documentElement;
|
|
1066
898
|
|
|
1067
899
|
if (dirty && leadingWhitespace) {
|
|
1068
900
|
body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
|
|
@@ -1084,7 +916,7 @@
|
|
|
1084
916
|
*/
|
|
1085
917
|
|
|
1086
918
|
|
|
1087
|
-
|
|
919
|
+
const _createIterator = function _createIterator(root) {
|
|
1088
920
|
return createNodeIterator.call(root.ownerDocument || root, root, // eslint-disable-next-line no-bitwise
|
|
1089
921
|
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
|
|
1090
922
|
};
|
|
@@ -1096,7 +928,7 @@
|
|
|
1096
928
|
*/
|
|
1097
929
|
|
|
1098
930
|
|
|
1099
|
-
|
|
931
|
+
const _isClobbered = function _isClobbered(elm) {
|
|
1100
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');
|
|
1101
933
|
};
|
|
1102
934
|
/**
|
|
@@ -1107,8 +939,8 @@
|
|
|
1107
939
|
*/
|
|
1108
940
|
|
|
1109
941
|
|
|
1110
|
-
|
|
1111
|
-
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';
|
|
1112
944
|
};
|
|
1113
945
|
/**
|
|
1114
946
|
* _executeHook
|
|
@@ -1120,12 +952,12 @@
|
|
|
1120
952
|
*/
|
|
1121
953
|
|
|
1122
954
|
|
|
1123
|
-
|
|
955
|
+
const _executeHook = function _executeHook(entryPoint, currentNode, data) {
|
|
1124
956
|
if (!hooks[entryPoint]) {
|
|
1125
957
|
return;
|
|
1126
958
|
}
|
|
1127
959
|
|
|
1128
|
-
arrayForEach(hooks[entryPoint],
|
|
960
|
+
arrayForEach(hooks[entryPoint], hook => {
|
|
1129
961
|
hook.call(DOMPurify, currentNode, data, CONFIG);
|
|
1130
962
|
});
|
|
1131
963
|
};
|
|
@@ -1141,8 +973,8 @@
|
|
|
1141
973
|
*/
|
|
1142
974
|
|
|
1143
975
|
|
|
1144
|
-
|
|
1145
|
-
|
|
976
|
+
const _sanitizeElements = function _sanitizeElements(currentNode) {
|
|
977
|
+
let content;
|
|
1146
978
|
/* Execute a hook if present */
|
|
1147
979
|
|
|
1148
980
|
_executeHook('beforeSanitizeElements', currentNode, null);
|
|
@@ -1157,11 +989,11 @@
|
|
|
1157
989
|
/* Now let's check the element's type and name */
|
|
1158
990
|
|
|
1159
991
|
|
|
1160
|
-
|
|
992
|
+
const tagName = transformCaseFunc(currentNode.nodeName);
|
|
1161
993
|
/* Execute a hook if present */
|
|
1162
994
|
|
|
1163
995
|
_executeHook('uponSanitizeElement', currentNode, {
|
|
1164
|
-
tagName
|
|
996
|
+
tagName,
|
|
1165
997
|
allowedTags: ALLOWED_TAGS
|
|
1166
998
|
});
|
|
1167
999
|
/* Detect mXSS attempts abusing namespace confusion */
|
|
@@ -1185,13 +1017,13 @@
|
|
|
1185
1017
|
|
|
1186
1018
|
|
|
1187
1019
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
1188
|
-
|
|
1189
|
-
|
|
1020
|
+
const parentNode = getParentNode(currentNode) || currentNode.parentNode;
|
|
1021
|
+
const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
|
|
1190
1022
|
|
|
1191
1023
|
if (childNodes && parentNode) {
|
|
1192
|
-
|
|
1024
|
+
const childCount = childNodes.length;
|
|
1193
1025
|
|
|
1194
|
-
for (
|
|
1026
|
+
for (let i = childCount - 1; i >= 0; --i) {
|
|
1195
1027
|
parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
|
|
1196
1028
|
}
|
|
1197
1029
|
}
|
|
@@ -1223,9 +1055,9 @@
|
|
|
1223
1055
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
|
1224
1056
|
/* Get the element's text content */
|
|
1225
1057
|
content = currentNode.textContent;
|
|
1226
|
-
content = stringReplace(content, MUSTACHE_EXPR
|
|
1227
|
-
content = stringReplace(content, ERB_EXPR
|
|
1228
|
-
content = stringReplace(content, TMPLIT_EXPR
|
|
1058
|
+
content = stringReplace(content, MUSTACHE_EXPR, ' ');
|
|
1059
|
+
content = stringReplace(content, ERB_EXPR, ' ');
|
|
1060
|
+
content = stringReplace(content, TMPLIT_EXPR, ' ');
|
|
1229
1061
|
|
|
1230
1062
|
if (currentNode.textContent !== content) {
|
|
1231
1063
|
arrayPush(DOMPurify.removed, {
|
|
@@ -1252,7 +1084,7 @@
|
|
|
1252
1084
|
// eslint-disable-next-line complexity
|
|
1253
1085
|
|
|
1254
1086
|
|
|
1255
|
-
|
|
1087
|
+
const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
1256
1088
|
/* Make sure attribute cannot clobber */
|
|
1257
1089
|
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
1258
1090
|
return false;
|
|
@@ -1263,7 +1095,7 @@
|
|
|
1263
1095
|
We don't need to check the value; it's always URI safe. */
|
|
1264
1096
|
|
|
1265
1097
|
|
|
1266
|
-
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]) {
|
|
1267
1099
|
if ( // First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
1268
1100
|
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1269
1101
|
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
|
|
@@ -1274,7 +1106,7 @@
|
|
|
1274
1106
|
}
|
|
1275
1107
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
1276
1108
|
|
|
1277
|
-
} 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 {
|
|
1278
1110
|
return false;
|
|
1279
1111
|
}
|
|
1280
1112
|
|
|
@@ -1288,7 +1120,7 @@
|
|
|
1288
1120
|
*/
|
|
1289
1121
|
|
|
1290
1122
|
|
|
1291
|
-
|
|
1123
|
+
const _basicCustomElementTest = function _basicCustomElementTest(tagName) {
|
|
1292
1124
|
return tagName.indexOf('-') > 0;
|
|
1293
1125
|
};
|
|
1294
1126
|
/**
|
|
@@ -1303,23 +1135,25 @@
|
|
|
1303
1135
|
*/
|
|
1304
1136
|
|
|
1305
1137
|
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1138
|
+
const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
1139
|
+
let attr;
|
|
1140
|
+
let value;
|
|
1141
|
+
let lcName;
|
|
1142
|
+
let l;
|
|
1311
1143
|
/* Execute a hook if present */
|
|
1312
1144
|
|
|
1313
1145
|
_executeHook('beforeSanitizeAttributes', currentNode, null);
|
|
1314
1146
|
|
|
1315
|
-
|
|
1147
|
+
const {
|
|
1148
|
+
attributes
|
|
1149
|
+
} = currentNode;
|
|
1316
1150
|
/* Check if we have attributes; if not we might have a text node */
|
|
1317
1151
|
|
|
1318
1152
|
if (!attributes) {
|
|
1319
1153
|
return;
|
|
1320
1154
|
}
|
|
1321
1155
|
|
|
1322
|
-
|
|
1156
|
+
const hookEvent = {
|
|
1323
1157
|
attrName: '',
|
|
1324
1158
|
attrValue: '',
|
|
1325
1159
|
keepAttr: true,
|
|
@@ -1330,9 +1164,10 @@
|
|
|
1330
1164
|
|
|
1331
1165
|
while (l--) {
|
|
1332
1166
|
attr = attributes[l];
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1167
|
+
const {
|
|
1168
|
+
name,
|
|
1169
|
+
namespaceURI
|
|
1170
|
+
} = attr;
|
|
1336
1171
|
value = name === 'value' ? attr.value : stringTrim(attr.value);
|
|
1337
1172
|
lcName = transformCaseFunc(name);
|
|
1338
1173
|
/* Execute a hook if present */
|
|
@@ -1372,14 +1207,14 @@
|
|
|
1372
1207
|
|
|
1373
1208
|
|
|
1374
1209
|
if (SAFE_FOR_TEMPLATES) {
|
|
1375
|
-
value = stringReplace(value, MUSTACHE_EXPR
|
|
1376
|
-
value = stringReplace(value, ERB_EXPR
|
|
1377
|
-
value = stringReplace(value, TMPLIT_EXPR
|
|
1210
|
+
value = stringReplace(value, MUSTACHE_EXPR, ' ');
|
|
1211
|
+
value = stringReplace(value, ERB_EXPR, ' ');
|
|
1212
|
+
value = stringReplace(value, TMPLIT_EXPR, ' ');
|
|
1378
1213
|
}
|
|
1379
1214
|
/* Is `value` valid for this attribute? */
|
|
1380
1215
|
|
|
1381
1216
|
|
|
1382
|
-
|
|
1217
|
+
const lcTag = transformCaseFunc(currentNode.nodeName);
|
|
1383
1218
|
|
|
1384
1219
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
1385
1220
|
continue;
|
|
@@ -1399,7 +1234,7 @@
|
|
|
1399
1234
|
/* Handle attributes that require Trusted Types */
|
|
1400
1235
|
|
|
1401
1236
|
|
|
1402
|
-
if (trustedTypesPolicy &&
|
|
1237
|
+
if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {
|
|
1403
1238
|
if (namespaceURI) ; else {
|
|
1404
1239
|
switch (trustedTypes.getAttributeType(lcTag, lcName)) {
|
|
1405
1240
|
case 'TrustedHTML':
|
|
@@ -1438,10 +1273,10 @@
|
|
|
1438
1273
|
*/
|
|
1439
1274
|
|
|
1440
1275
|
|
|
1441
|
-
|
|
1442
|
-
|
|
1276
|
+
const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
|
|
1277
|
+
let shadowNode;
|
|
1443
1278
|
|
|
1444
|
-
|
|
1279
|
+
const shadowIterator = _createIterator(fragment);
|
|
1445
1280
|
/* Execute a hook if present */
|
|
1446
1281
|
|
|
1447
1282
|
|
|
@@ -1483,11 +1318,11 @@
|
|
|
1483
1318
|
|
|
1484
1319
|
|
|
1485
1320
|
DOMPurify.sanitize = function (dirty) {
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1321
|
+
let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
1322
|
+
let body;
|
|
1323
|
+
let importedNode;
|
|
1324
|
+
let currentNode;
|
|
1325
|
+
let returnNode;
|
|
1491
1326
|
/* Make sure we have a string to sanitize.
|
|
1492
1327
|
DO NOT return early, as this will return the wrong type if
|
|
1493
1328
|
the user has requested a DOM object rather than a string */
|
|
@@ -1537,7 +1372,7 @@
|
|
|
1537
1372
|
if (IN_PLACE) {
|
|
1538
1373
|
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
1539
1374
|
if (dirty.nodeName) {
|
|
1540
|
-
|
|
1375
|
+
const tagName = transformCaseFunc(dirty.nodeName);
|
|
1541
1376
|
|
|
1542
1377
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
1543
1378
|
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
@@ -1583,7 +1418,7 @@
|
|
|
1583
1418
|
/* Get node iterator */
|
|
1584
1419
|
|
|
1585
1420
|
|
|
1586
|
-
|
|
1421
|
+
const nodeIterator = _createIterator(IN_PLACE ? dirty : body);
|
|
1587
1422
|
/* Now start iterating over the created document */
|
|
1588
1423
|
|
|
1589
1424
|
|
|
@@ -1638,7 +1473,7 @@
|
|
|
1638
1473
|
return returnNode;
|
|
1639
1474
|
}
|
|
1640
1475
|
|
|
1641
|
-
|
|
1476
|
+
let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
|
1642
1477
|
/* Serialize doctype if allowed */
|
|
1643
1478
|
|
|
1644
1479
|
if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
|
|
@@ -1648,9 +1483,9 @@
|
|
|
1648
1483
|
|
|
1649
1484
|
|
|
1650
1485
|
if (SAFE_FOR_TEMPLATES) {
|
|
1651
|
-
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR
|
|
1652
|
-
serializedHTML = stringReplace(serializedHTML, ERB_EXPR
|
|
1653
|
-
serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR
|
|
1486
|
+
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR, ' ');
|
|
1487
|
+
serializedHTML = stringReplace(serializedHTML, ERB_EXPR, ' ');
|
|
1488
|
+
serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR, ' ');
|
|
1654
1489
|
}
|
|
1655
1490
|
|
|
1656
1491
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
|
@@ -1697,8 +1532,8 @@
|
|
|
1697
1532
|
_parseConfig({});
|
|
1698
1533
|
}
|
|
1699
1534
|
|
|
1700
|
-
|
|
1701
|
-
|
|
1535
|
+
const lcTag = transformCaseFunc(tag);
|
|
1536
|
+
const lcName = transformCaseFunc(attr);
|
|
1702
1537
|
return _isValidAttribute(lcTag, lcName, value);
|
|
1703
1538
|
};
|
|
1704
1539
|
/**
|