dompurify 1.0.2 → 1.0.3
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 +8 -3
- package/dist/purify.cjs.js +148 -138
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +148 -138
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +148 -138
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +1 -1
- package/dist/purify.min.js.map +1 -1
- package/package-lock.json +6620 -0
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG.
|
|
6
6
|
|
|
7
|
-
It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version 1.0.
|
|
7
|
+
It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version 1.0.3!
|
|
8
8
|
|
|
9
9
|
DOMPurify is written in JavaScript and works in all modern browsers (Safari, Opera (15+), Internet Explorer (10+), Edge, Firefox and Chrome - as well as almost anything else using Blink or WebKit). It doesn't break on MSIE6 or other legacy browsers. It either uses [a fall-back](#what-about-older-browsers-like-msie8) or simply does nothing.
|
|
10
10
|
|
|
11
|
-
Our automated tests cover [16 different browsers](https://github.com/cure53/DOMPurify/blob/master/test/karma.
|
|
11
|
+
Our automated tests cover [16 different browsers](https://github.com/cure53/DOMPurify/blob/master/test/karma.custom-launchers.config.js#L5) right now, more to come. We also cover Node.js v4.0.0, v5.0.0 and v6.0.0, running DOMPurify on [jsdom](https://github.com/tmpvar/jsdom).
|
|
12
12
|
|
|
13
13
|
DOMPurify is written by security people who have vast background in web attacks and XSS. Fear not. For more details please also read about our [Security Goals & Threat Model](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model). Please, read it. Like, really.
|
|
14
14
|
|
|
@@ -139,9 +139,14 @@ var clean = DOMPurify.sanitize(dirty, {ADD_ATTR: ['my-attr']});
|
|
|
139
139
|
var clean = DOMPurify.sanitize(dirty, {ALLOW_DATA_ATTR: false});
|
|
140
140
|
|
|
141
141
|
// allow external protocol handlers in URL attributes (default is false)
|
|
142
|
-
// by default only http, https, ftp, ftps, tel and
|
|
142
|
+
// by default only http, https, ftp, ftps, tel, mailto, callto, cid and xmpp are allowed.
|
|
143
143
|
var clean = DOMPurify.sanitize(dirty, {ALLOW_UNKNOWN_PROTOCOLS: true});
|
|
144
144
|
|
|
145
|
+
// allow specific protocols handlers in URL attributes (default is false)
|
|
146
|
+
// by default only http, https, ftp, ftps, tel, mailto, callto, cid and xmpp are allowed.
|
|
147
|
+
// Default RegExp: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
|
|
148
|
+
var clean = DOMPurify.sanitize(dirty, {ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp|xxx):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;});
|
|
149
|
+
|
|
145
150
|
// return a DOM HTMLBodyElement instead of an HTML string (default is false)
|
|
146
151
|
var clean = DOMPurify.sanitize(dirty, {RETURN_DOM: true});
|
|
147
152
|
|
package/dist/purify.cjs.js
CHANGED
|
@@ -11,7 +11,7 @@ var mathMl = ['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi',
|
|
|
11
11
|
|
|
12
12
|
var text = ['#text'];
|
|
13
13
|
|
|
14
|
-
var html$1 = ['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'coords', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'span', 'srclang', 'start', 'src', 'step', 'style', 'summary', 'tabindex', 'title', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns'];
|
|
14
|
+
var html$1 = ['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns'];
|
|
15
15
|
|
|
16
16
|
var svg$1 = ['accent-height', 'accumulate', 'additivive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', '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', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', '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'];
|
|
17
17
|
|
|
@@ -43,6 +43,14 @@ function clone(object) {
|
|
|
43
43
|
return newObject;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
var MUSTACHE_EXPR = /\{\{[\s\S]*|[\s\S]*\}\}/gm; // Specify template detection regex for SAFE_FOR_TEMPLATES mode
|
|
47
|
+
var ERB_EXPR = /<%[\s\S]*|[\s\S]*%>/gm;
|
|
48
|
+
var DATA_ATTR = /^data-[\-\w.\u00B7-\uFFFF]/; // eslint-disable-line no-useless-escape
|
|
49
|
+
var ARIA_ATTR = /^aria-[\-\w]+$/; // eslint-disable-line no-useless-escape
|
|
50
|
+
var IS_ALLOWED_URI = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i; // eslint-disable-line no-useless-escape
|
|
51
|
+
var IS_SCRIPT_OR_DATA = /^(?:\w+script|data):/i;
|
|
52
|
+
var ATTR_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g; // This needs to be extensive thanks to Webkit/Blink's behavior
|
|
53
|
+
|
|
46
54
|
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
47
55
|
|
|
48
56
|
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
|
@@ -59,15 +67,15 @@ function createDOMPurify() {
|
|
|
59
67
|
};
|
|
60
68
|
|
|
61
69
|
/**
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
DOMPurify.version = '1.0.
|
|
70
|
+
* Version label, exposed for easier checks
|
|
71
|
+
* if DOMPurify is up to date or not
|
|
72
|
+
*/
|
|
73
|
+
DOMPurify.version = '1.0.3';
|
|
66
74
|
|
|
67
75
|
/**
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
* Array of elements that DOMPurify removed during sanitation.
|
|
77
|
+
* Empty if nothing was removed.
|
|
78
|
+
*/
|
|
71
79
|
DOMPurify.removed = [];
|
|
72
80
|
|
|
73
81
|
if (!window || !window.document || window.document.nodeType !== 9) {
|
|
@@ -122,14 +130,23 @@ function createDOMPurify() {
|
|
|
122
130
|
var hooks = {};
|
|
123
131
|
|
|
124
132
|
/**
|
|
125
|
-
|
|
126
|
-
|
|
133
|
+
* Expose whether this browser supports running the full DOMPurify.
|
|
134
|
+
*/
|
|
127
135
|
DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && document.documentMode !== 9;
|
|
128
136
|
|
|
137
|
+
var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
|
|
138
|
+
ERB_EXPR$$1 = ERB_EXPR,
|
|
139
|
+
DATA_ATTR$$1 = DATA_ATTR,
|
|
140
|
+
ARIA_ATTR$$1 = ARIA_ATTR,
|
|
141
|
+
IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,
|
|
142
|
+
ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;
|
|
129
146
|
/**
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
147
|
+
* We consider the elements and attributes below to be safe. Ideally
|
|
148
|
+
* don't add any new ones but feel free to remove unwanted ones.
|
|
149
|
+
*/
|
|
133
150
|
|
|
134
151
|
/* allowed element names */
|
|
135
152
|
var ALLOWED_TAGS = null;
|
|
@@ -162,10 +179,6 @@ function createDOMPurify() {
|
|
|
162
179
|
*/
|
|
163
180
|
var SAFE_FOR_TEMPLATES = false;
|
|
164
181
|
|
|
165
|
-
/* Specify template detection regex for SAFE_FOR_TEMPLATES mode */
|
|
166
|
-
var MUSTACHE_EXPR = /\{\{[\s\S]*|[\s\S]*\}\}/gm;
|
|
167
|
-
var ERB_EXPR = /<%[\s\S]*|[\s\S]*%>/gm;
|
|
168
|
-
|
|
169
182
|
/* Decide if document with <html>... should be returned */
|
|
170
183
|
var WHOLE_DOCUMENT = false;
|
|
171
184
|
|
|
@@ -217,17 +230,16 @@ function createDOMPurify() {
|
|
|
217
230
|
var formElement = document.createElement('form');
|
|
218
231
|
|
|
219
232
|
/**
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
233
|
+
* _parseConfig
|
|
234
|
+
*
|
|
235
|
+
* @param optional config literal
|
|
236
|
+
*/
|
|
224
237
|
// eslint-disable-next-line complexity
|
|
225
238
|
var _parseConfig = function _parseConfig(cfg) {
|
|
226
239
|
/* Shield configuration object from tampering */
|
|
227
240
|
if ((typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {
|
|
228
241
|
cfg = {};
|
|
229
242
|
}
|
|
230
|
-
|
|
231
243
|
/* Set configuration parameters */
|
|
232
244
|
ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
|
|
233
245
|
ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
|
|
@@ -247,6 +259,8 @@ function createDOMPurify() {
|
|
|
247
259
|
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
|
248
260
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
249
261
|
|
|
262
|
+
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
263
|
+
|
|
250
264
|
if (SAFE_FOR_TEMPLATES) {
|
|
251
265
|
ALLOW_DATA_ATTR = false;
|
|
252
266
|
}
|
|
@@ -312,10 +326,10 @@ function createDOMPurify() {
|
|
|
312
326
|
};
|
|
313
327
|
|
|
314
328
|
/**
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
329
|
+
* _forceRemove
|
|
330
|
+
*
|
|
331
|
+
* @param a DOM node
|
|
332
|
+
*/
|
|
319
333
|
var _forceRemove = function _forceRemove(node) {
|
|
320
334
|
DOMPurify.removed.push({ element: node });
|
|
321
335
|
try {
|
|
@@ -326,11 +340,11 @@ function createDOMPurify() {
|
|
|
326
340
|
};
|
|
327
341
|
|
|
328
342
|
/**
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
343
|
+
* _removeAttribute
|
|
344
|
+
*
|
|
345
|
+
* @param an Attribute name
|
|
346
|
+
* @param a DOM node
|
|
347
|
+
*/
|
|
334
348
|
var _removeAttribute = function _removeAttribute(name, node) {
|
|
335
349
|
DOMPurify.removed.push({
|
|
336
350
|
attribute: node.getAttributeNode(name),
|
|
@@ -340,11 +354,11 @@ function createDOMPurify() {
|
|
|
340
354
|
};
|
|
341
355
|
|
|
342
356
|
/**
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
357
|
+
* _initDocument
|
|
358
|
+
*
|
|
359
|
+
* @param a string of dirty markup
|
|
360
|
+
* @return a DOM, filled with the dirty markup
|
|
361
|
+
*/
|
|
348
362
|
var _initDocument = function _initDocument(dirty) {
|
|
349
363
|
/* Create a HTML document */
|
|
350
364
|
var doc = void 0;
|
|
@@ -420,11 +434,11 @@ function createDOMPurify() {
|
|
|
420
434
|
}
|
|
421
435
|
|
|
422
436
|
/**
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
437
|
+
* _createIterator
|
|
438
|
+
*
|
|
439
|
+
* @param document/fragment to create iterator for
|
|
440
|
+
* @return iterator instance
|
|
441
|
+
*/
|
|
428
442
|
var _createIterator = function _createIterator(root) {
|
|
429
443
|
return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {
|
|
430
444
|
return NodeFilter.FILTER_ACCEPT;
|
|
@@ -432,11 +446,11 @@ function createDOMPurify() {
|
|
|
432
446
|
};
|
|
433
447
|
|
|
434
448
|
/**
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
449
|
+
* _isClobbered
|
|
450
|
+
*
|
|
451
|
+
* @param element to check for clobbering attacks
|
|
452
|
+
* @return true if clobbered, false if safe
|
|
453
|
+
*/
|
|
440
454
|
var _isClobbered = function _isClobbered(elm) {
|
|
441
455
|
if (elm instanceof Text || elm instanceof Comment) {
|
|
442
456
|
return false;
|
|
@@ -448,22 +462,22 @@ function createDOMPurify() {
|
|
|
448
462
|
};
|
|
449
463
|
|
|
450
464
|
/**
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
465
|
+
* _isNode
|
|
466
|
+
*
|
|
467
|
+
* @param object to check whether it's a DOM node
|
|
468
|
+
* @return true is object is a DOM node
|
|
469
|
+
*/
|
|
456
470
|
var _isNode = function _isNode(obj) {
|
|
457
471
|
return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? obj instanceof Node : obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && typeof obj.nodeType === 'number' && typeof obj.nodeName === 'string';
|
|
458
472
|
};
|
|
459
473
|
|
|
460
474
|
/**
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
475
|
+
* _executeHook
|
|
476
|
+
* Execute user configurable hooks
|
|
477
|
+
*
|
|
478
|
+
* @param {String} entryPoint Name of the hook's entry point
|
|
479
|
+
* @param {Node} currentNode
|
|
480
|
+
*/
|
|
467
481
|
var _executeHook = function _executeHook(entryPoint, currentNode, data) {
|
|
468
482
|
if (!hooks[entryPoint]) {
|
|
469
483
|
return;
|
|
@@ -475,15 +489,15 @@ function createDOMPurify() {
|
|
|
475
489
|
};
|
|
476
490
|
|
|
477
491
|
/**
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
492
|
+
* _sanitizeElements
|
|
493
|
+
*
|
|
494
|
+
* @protect nodeName
|
|
495
|
+
* @protect textContent
|
|
496
|
+
* @protect removeChild
|
|
497
|
+
*
|
|
498
|
+
* @param node to check for permission to exist
|
|
499
|
+
* @return true if node was killed, false if left alive
|
|
500
|
+
*/
|
|
487
501
|
var _sanitizeElements = function _sanitizeElements(currentNode) {
|
|
488
502
|
var content = void 0;
|
|
489
503
|
|
|
@@ -527,8 +541,8 @@ function createDOMPurify() {
|
|
|
527
541
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
|
528
542
|
/* Get the element's text content */
|
|
529
543
|
content = currentNode.textContent;
|
|
530
|
-
content = content.replace(MUSTACHE_EXPR, ' ');
|
|
531
|
-
content = content.replace(ERB_EXPR, ' ');
|
|
544
|
+
content = content.replace(MUSTACHE_EXPR$$1, ' ');
|
|
545
|
+
content = content.replace(ERB_EXPR$$1, ' ');
|
|
532
546
|
if (currentNode.textContent !== content) {
|
|
533
547
|
DOMPurify.removed.push({ element: currentNode.cloneNode() });
|
|
534
548
|
currentNode.textContent = content;
|
|
@@ -541,24 +555,17 @@ function createDOMPurify() {
|
|
|
541
555
|
return false;
|
|
542
556
|
};
|
|
543
557
|
|
|
544
|
-
var DATA_ATTR = /^data-[\-\w.\u00B7-\uFFFF]/; // eslint-disable-line no-useless-escape
|
|
545
|
-
var ARIA_ATTR = /^aria-[\-\w]+$/; // eslint-disable-line no-useless-escape
|
|
546
|
-
var IS_ALLOWED_URI = /^(?:(?:(?:f|ht)tps?|mailto|tel):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i; // eslint-disable-line no-useless-escape
|
|
547
|
-
var IS_SCRIPT_OR_DATA = /^(?:\w+script|data):/i;
|
|
548
|
-
/* This needs to be extensive thanks to Webkit/Blink's behavior */
|
|
549
|
-
var ATTR_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g;
|
|
550
|
-
|
|
551
558
|
/**
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
559
|
+
* _sanitizeAttributes
|
|
560
|
+
*
|
|
561
|
+
* @protect attributes
|
|
562
|
+
* @protect nodeName
|
|
563
|
+
* @protect removeAttribute
|
|
564
|
+
* @protect setAttribute
|
|
565
|
+
*
|
|
566
|
+
* @param node to sanitize
|
|
567
|
+
* @return void
|
|
568
|
+
*/
|
|
562
569
|
// eslint-disable-next-line complexity
|
|
563
570
|
var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
564
571
|
var attr = void 0;
|
|
@@ -633,23 +640,23 @@ function createDOMPurify() {
|
|
|
633
640
|
}
|
|
634
641
|
|
|
635
642
|
/* Make sure attribute cannot clobber */
|
|
636
|
-
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in
|
|
643
|
+
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
637
644
|
continue;
|
|
638
645
|
}
|
|
639
646
|
|
|
640
647
|
/* Sanitize attribute content to be template-safe */
|
|
641
648
|
if (SAFE_FOR_TEMPLATES) {
|
|
642
|
-
value = value.replace(MUSTACHE_EXPR, ' ');
|
|
643
|
-
value = value.replace(ERB_EXPR, ' ');
|
|
649
|
+
value = value.replace(MUSTACHE_EXPR$$1, ' ');
|
|
650
|
+
value = value.replace(ERB_EXPR$$1, ' ');
|
|
644
651
|
}
|
|
645
652
|
|
|
646
653
|
/* Allow valid data-* attributes: At least one character after "-"
|
|
647
654
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
648
655
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
649
656
|
We don't need to check the value; it's always URI safe. */
|
|
650
|
-
if (ALLOW_DATA_ATTR && DATA_ATTR.test(lcName)) {
|
|
657
|
+
if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) {
|
|
651
658
|
// This attribute is safe
|
|
652
|
-
} else if (ALLOW_ARIA_ATTR && ARIA_ATTR.test(lcName)) {
|
|
659
|
+
} else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) {
|
|
653
660
|
// This attribute is safe
|
|
654
661
|
/* Otherwise, check the name is permitted */
|
|
655
662
|
} else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
@@ -660,7 +667,7 @@ function createDOMPurify() {
|
|
|
660
667
|
// This attribute is safe
|
|
661
668
|
/* Check no script, data or unknown possibly unsafe URI
|
|
662
669
|
unless we know URI values are safe for that attribute */
|
|
663
|
-
} else if (IS_ALLOWED_URI.test(value.replace(ATTR_WHITESPACE, ''))) {
|
|
670
|
+
} else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
|
|
664
671
|
// This attribute is safe
|
|
665
672
|
/* Keep image data URIs alive if src/xlink:href is allowed */
|
|
666
673
|
} else if ((lcName === 'src' || lcName === 'xlink:href') && value.indexOf('data:') === 0 && DATA_URI_TAGS[currentNode.nodeName.toLowerCase()]) {
|
|
@@ -668,7 +675,7 @@ function createDOMPurify() {
|
|
|
668
675
|
/* Allow unknown protocols: This provides support for links that
|
|
669
676
|
are handled by protocol handlers which may be unknown ahead of
|
|
670
677
|
time, e.g. fb:, spotify: */
|
|
671
|
-
} else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA.test(value.replace(ATTR_WHITESPACE, ''))) {
|
|
678
|
+
} else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
|
|
672
679
|
// This attribute is safe
|
|
673
680
|
/* Check for binary attributes */
|
|
674
681
|
// eslint-disable-next-line no-negated-condition
|
|
@@ -691,11 +698,11 @@ function createDOMPurify() {
|
|
|
691
698
|
};
|
|
692
699
|
|
|
693
700
|
/**
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
701
|
+
* _sanitizeShadowDOM
|
|
702
|
+
*
|
|
703
|
+
* @param fragment to iterate over recursively
|
|
704
|
+
* @return void
|
|
705
|
+
*/
|
|
699
706
|
var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
|
|
700
707
|
var shadowNode = void 0;
|
|
701
708
|
var shadowIterator = _createIterator(fragment);
|
|
@@ -726,12 +733,12 @@ function createDOMPurify() {
|
|
|
726
733
|
};
|
|
727
734
|
|
|
728
735
|
/**
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
736
|
+
* Sanitize
|
|
737
|
+
* Public method providing core sanitation functionality
|
|
738
|
+
*
|
|
739
|
+
* @param {String|Node} dirty string or DOM node
|
|
740
|
+
* @param {Object} configuration object
|
|
741
|
+
*/
|
|
735
742
|
// eslint-disable-next-line complexity
|
|
736
743
|
DOMPurify.sanitize = function (dirty, cfg) {
|
|
737
744
|
var body = void 0;
|
|
@@ -753,6 +760,9 @@ function createDOMPurify() {
|
|
|
753
760
|
throw new TypeError('toString is not a function');
|
|
754
761
|
} else {
|
|
755
762
|
dirty = dirty.toString();
|
|
763
|
+
if (typeof dirty !== 'string') {
|
|
764
|
+
throw new TypeError('dirty is not a string, aborting');
|
|
765
|
+
}
|
|
756
766
|
}
|
|
757
767
|
}
|
|
758
768
|
|
|
@@ -861,35 +871,35 @@ function createDOMPurify() {
|
|
|
861
871
|
};
|
|
862
872
|
|
|
863
873
|
/**
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
874
|
+
* Public method to set the configuration once
|
|
875
|
+
* setConfig
|
|
876
|
+
*
|
|
877
|
+
* @param {Object} configuration object
|
|
878
|
+
* @return void
|
|
879
|
+
*/
|
|
870
880
|
DOMPurify.setConfig = function (cfg) {
|
|
871
881
|
_parseConfig(cfg);
|
|
872
882
|
SET_CONFIG = true;
|
|
873
883
|
};
|
|
874
884
|
|
|
875
885
|
/**
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
886
|
+
* Public method to remove the configuration
|
|
887
|
+
* clearConfig
|
|
888
|
+
*
|
|
889
|
+
* @return void
|
|
890
|
+
*/
|
|
881
891
|
DOMPurify.clearConfig = function () {
|
|
882
892
|
CONFIG = null;
|
|
883
893
|
SET_CONFIG = false;
|
|
884
894
|
};
|
|
885
895
|
|
|
886
896
|
/**
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
897
|
+
* AddHook
|
|
898
|
+
* Public method to add DOMPurify hooks
|
|
899
|
+
*
|
|
900
|
+
* @param {String} entryPoint
|
|
901
|
+
* @param {Function} hookFunction
|
|
902
|
+
*/
|
|
893
903
|
DOMPurify.addHook = function (entryPoint, hookFunction) {
|
|
894
904
|
if (typeof hookFunction !== 'function') {
|
|
895
905
|
return;
|
|
@@ -899,13 +909,13 @@ function createDOMPurify() {
|
|
|
899
909
|
};
|
|
900
910
|
|
|
901
911
|
/**
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
912
|
+
* RemoveHook
|
|
913
|
+
* Public method to remove a DOMPurify hook at a given entryPoint
|
|
914
|
+
* (pops it from the stack of hooks if more are present)
|
|
915
|
+
*
|
|
916
|
+
* @param {String} entryPoint
|
|
917
|
+
* @return void
|
|
918
|
+
*/
|
|
909
919
|
DOMPurify.removeHook = function (entryPoint) {
|
|
910
920
|
if (hooks[entryPoint]) {
|
|
911
921
|
hooks[entryPoint].pop();
|
|
@@ -913,12 +923,12 @@ function createDOMPurify() {
|
|
|
913
923
|
};
|
|
914
924
|
|
|
915
925
|
/**
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
926
|
+
* RemoveHooks
|
|
927
|
+
* Public method to remove all DOMPurify hooks at a given entryPoint
|
|
928
|
+
*
|
|
929
|
+
* @param {String} entryPoint
|
|
930
|
+
* @return void
|
|
931
|
+
*/
|
|
922
932
|
DOMPurify.removeHooks = function (entryPoint) {
|
|
923
933
|
if (hooks[entryPoint]) {
|
|
924
934
|
hooks[entryPoint] = [];
|
|
@@ -926,11 +936,11 @@ function createDOMPurify() {
|
|
|
926
936
|
};
|
|
927
937
|
|
|
928
938
|
/**
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
939
|
+
* RemoveAllHooks
|
|
940
|
+
* Public method to remove all DOMPurify hooks
|
|
941
|
+
*
|
|
942
|
+
* @return void
|
|
943
|
+
*/
|
|
934
944
|
DOMPurify.removeAllHooks = function () {
|
|
935
945
|
hooks = {};
|
|
936
946
|
};
|