dompurify 1.0.9 → 1.0.10
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 +24 -4
- package/dist/purify.cjs.js +70 -20
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +70 -20
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +70 -20
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +1 -1
- package/dist/purify.min.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG.
|
|
8
8
|
|
|
9
|
-
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.
|
|
9
|
+
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.10.
|
|
10
10
|
|
|
11
11
|
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.
|
|
12
12
|
|
|
13
|
-
Our automated tests cover [
|
|
13
|
+
Our automated tests cover [25 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 v8.0.0, v9.0.0 and v10.0.0, running DOMPurify on [jsdom](https://github.com/tmpvar/jsdom).
|
|
14
14
|
|
|
15
15
|
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.
|
|
16
16
|
|
|
@@ -110,7 +110,24 @@ DOMPurify offers a fall-back behavior for older MSIE browsers. It uses the MSIE-
|
|
|
110
110
|
|
|
111
111
|
If not even `toStaticHTML` is supported, DOMPurify does nothing at all. It simply returns exactly the string that you fed it.
|
|
112
112
|
|
|
113
|
-
##
|
|
113
|
+
## What about DOMPurify and Trusted Types?
|
|
114
|
+
|
|
115
|
+
In version 1.0.9, support for [Trusted Types API](https://github.com/WICG/trusted-types) was added to DOMPurify.
|
|
116
|
+
|
|
117
|
+
When `DOMPurify.sanitize` is used in the environment where the Trusted Types API is available (this happens e.g. in Chrome `chrome://flags/#enable-experimental-web-platform-features`), it returns a `TrustedHTML` value instead of a string (the behavior for `RETURN_DOM`, `RETURN_DOM_FRAGMENT`, and `RETURN_DOM_IMPORT` config options does not change).
|
|
118
|
+
|
|
119
|
+
That return value is implicitly casted to a string when needed, returning the actual sanitized HTML snippet. In particular, you can directly use it with DOM sinks like `innerHTML`, or concatenate it with other strings. For most use cases, the API change does not introduce any visible change.
|
|
120
|
+
|
|
121
|
+
That said, `TrustedHTML` values are intentionally immutable, and don't inherit from `String.prototype`. In rare cases where you expect the value to implement String prototype functions (e.g. if you want to `String.replace` the sanitized output), cast the value to a string like so:
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
const sanitizedAsString = (DOMPurify.sanitize(foo) + '');
|
|
125
|
+
sanitizedAsString.replace(...)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Please note, that if that change breaks your application, you *might* be doing something wrong. The sanitized HTML snippet should not be modified, as it might introduce XSS vulnerabilities.
|
|
129
|
+
|
|
130
|
+
## Can I configure DOMPurify?
|
|
114
131
|
|
|
115
132
|
Yes. The included default configuration values are pretty good already - but you can of course override them. Check out the [`/demos`](https://github.com/cure53/DOMPurify/tree/master/demos) folder to see a bunch of examples on how you can [customize DOMPurify](https://github.com/cure53/DOMPurify/tree/master/demos#what-is-this).
|
|
116
133
|
|
|
@@ -119,6 +136,9 @@ Yes. The included default configuration values are pretty good already - but you
|
|
|
119
136
|
var clean = DOMPurify.sanitize(dirty, {SAFE_FOR_JQUERY: true});
|
|
120
137
|
|
|
121
138
|
// strip {{ ... }} and <% ... %> to make output safe for template systems
|
|
139
|
+
// be careful please, this mode is not recommended for production usage.
|
|
140
|
+
// allowing template parsing in user-controlled HTML is not advised at all.
|
|
141
|
+
// only use this mode if there is really no alternative.
|
|
122
142
|
var clean = DOMPurify.sanitize(dirty, {SAFE_FOR_TEMPLATES: true});
|
|
123
143
|
|
|
124
144
|
// allow only <b>
|
|
@@ -271,7 +291,7 @@ Several people need to be listed here!
|
|
|
271
291
|
|
|
272
292
|
Big thanks also go to [@ydaniv](https://github.com/ydaniv), [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro) and [@fhemberger](https://twitter.com/fhemberger)!
|
|
273
293
|
|
|
274
|
-
Further, thanks [@neilj](https://twitter.com/neilj) and [@0xsobky](https://twitter.com/0xsobky) for their code reviews and countless small optimizations, fixes and beautifications.
|
|
294
|
+
Further, thanks [@neilj](https://twitter.com/neilj) and [@0xsobky](https://twitter.com/0xsobky) for their code reviews and countless small optimizations, fixes and beautifications. Thanks also go out to [@kkotowicz](https://twitter.com/kkotowicz) for his Trusted Types implementation and the connected section on our README page.
|
|
275
295
|
|
|
276
296
|
Big thanks also go to [@tdeekens](https://twitter.com/tdeekens) for doing all the hard work and getting us on track with Travis CI and BrowserStack. And thanks to [@Joris-van-der-Wel](https://github.com/Joris-van-der-Wel) for setting up DOMPurify for jsdom and creating the additional test suite. And again [@tdeekens](https://twitter.com/tdeekens) for his [incredible efforts](https://github.com/cure53/DOMPurify/pull/206) and contribution to refactor DOMPurify into using ES201x, proper build tools, better test coverage and much more!
|
|
277
297
|
|
package/dist/purify.cjs.js
CHANGED
|
@@ -21,7 +21,7 @@ var freeze$2 = Object.freeze || function (x) {
|
|
|
21
21
|
|
|
22
22
|
var html$1 = freeze$2(['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']);
|
|
23
23
|
|
|
24
|
-
var svg$1 = freeze$2(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', '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', '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']);
|
|
24
|
+
var svg$1 = freeze$2(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', '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', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
|
|
25
25
|
|
|
26
26
|
var mathMl$1 = freeze$2(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', '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']);
|
|
27
27
|
|
|
@@ -47,30 +47,39 @@ function addToSet(set, array) {
|
|
|
47
47
|
// Prevent prototype setters from intercepting set as a this value.
|
|
48
48
|
setPrototypeOf(set, null);
|
|
49
49
|
}
|
|
50
|
+
|
|
50
51
|
var l = array.length;
|
|
51
52
|
while (l--) {
|
|
52
53
|
var element = array[l];
|
|
53
54
|
if (typeof element === 'string') {
|
|
54
55
|
var lcElement = element.toLowerCase();
|
|
55
56
|
if (lcElement !== element) {
|
|
56
|
-
|
|
57
|
+
// Config presets (e.g. tags.js, attrs.js) are immutable.
|
|
58
|
+
if (!Object.isFrozen(array)) {
|
|
59
|
+
array[l] = lcElement;
|
|
60
|
+
}
|
|
61
|
+
|
|
57
62
|
element = lcElement;
|
|
58
63
|
}
|
|
59
64
|
}
|
|
65
|
+
|
|
60
66
|
set[element] = true;
|
|
61
67
|
}
|
|
68
|
+
|
|
62
69
|
return set;
|
|
63
70
|
}
|
|
64
71
|
|
|
65
72
|
/* Shallow clone an object */
|
|
66
73
|
function clone(object) {
|
|
67
74
|
var newObject = {};
|
|
75
|
+
|
|
68
76
|
var property = void 0;
|
|
69
77
|
for (property in object) {
|
|
70
78
|
if (apply$1(hasOwnProperty, object, [property])) {
|
|
71
79
|
newObject[property] = object[property];
|
|
72
80
|
}
|
|
73
81
|
}
|
|
82
|
+
|
|
74
83
|
return newObject;
|
|
75
84
|
}
|
|
76
85
|
|
|
@@ -138,7 +147,7 @@ var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes,
|
|
|
138
147
|
return html$$1;
|
|
139
148
|
}
|
|
140
149
|
});
|
|
141
|
-
} catch (
|
|
150
|
+
} catch (error) {
|
|
142
151
|
// Policy creation failed (most likely another DOMPurify script has
|
|
143
152
|
// already run). Skip creating the policy, as this will only cause errors
|
|
144
153
|
// if TT are enforced.
|
|
@@ -158,7 +167,7 @@ function createDOMPurify() {
|
|
|
158
167
|
* Version label, exposed for easier checks
|
|
159
168
|
* if DOMPurify is up to date or not
|
|
160
169
|
*/
|
|
161
|
-
DOMPurify.version = '1.0.
|
|
170
|
+
DOMPurify.version = '1.0.10';
|
|
162
171
|
|
|
163
172
|
/**
|
|
164
173
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -337,6 +346,7 @@ function createDOMPurify() {
|
|
|
337
346
|
if (!cfg || (typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {
|
|
338
347
|
cfg = {};
|
|
339
348
|
}
|
|
349
|
+
|
|
340
350
|
/* Set configuration parameters */
|
|
341
351
|
ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
|
|
342
352
|
ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
|
|
@@ -375,16 +385,19 @@ function createDOMPurify() {
|
|
|
375
385
|
addToSet(ALLOWED_TAGS, html);
|
|
376
386
|
addToSet(ALLOWED_ATTR, html$1);
|
|
377
387
|
}
|
|
388
|
+
|
|
378
389
|
if (USE_PROFILES.svg === true) {
|
|
379
390
|
addToSet(ALLOWED_TAGS, svg);
|
|
380
391
|
addToSet(ALLOWED_ATTR, svg$1);
|
|
381
392
|
addToSet(ALLOWED_ATTR, xml);
|
|
382
393
|
}
|
|
394
|
+
|
|
383
395
|
if (USE_PROFILES.svgFilters === true) {
|
|
384
396
|
addToSet(ALLOWED_TAGS, svgFilters);
|
|
385
397
|
addToSet(ALLOWED_ATTR, svg$1);
|
|
386
398
|
addToSet(ALLOWED_ATTR, xml);
|
|
387
399
|
}
|
|
400
|
+
|
|
388
401
|
if (USE_PROFILES.mathMl === true) {
|
|
389
402
|
addToSet(ALLOWED_TAGS, mathMl);
|
|
390
403
|
addToSet(ALLOWED_ATTR, mathMl$1);
|
|
@@ -397,14 +410,18 @@ function createDOMPurify() {
|
|
|
397
410
|
if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
|
398
411
|
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
399
412
|
}
|
|
413
|
+
|
|
400
414
|
addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
|
|
401
415
|
}
|
|
416
|
+
|
|
402
417
|
if (cfg.ADD_ATTR) {
|
|
403
418
|
if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
|
|
404
419
|
ALLOWED_ATTR = clone(ALLOWED_ATTR);
|
|
405
420
|
}
|
|
421
|
+
|
|
406
422
|
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
|
|
407
423
|
}
|
|
424
|
+
|
|
408
425
|
if (cfg.ADD_URI_SAFE_ATTR) {
|
|
409
426
|
addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
|
|
410
427
|
}
|
|
@@ -442,7 +459,7 @@ function createDOMPurify() {
|
|
|
442
459
|
DOMPurify.removed.push({ element: node });
|
|
443
460
|
try {
|
|
444
461
|
node.parentNode.removeChild(node);
|
|
445
|
-
} catch (
|
|
462
|
+
} catch (error) {
|
|
446
463
|
node.outerHTML = emptyHTML;
|
|
447
464
|
}
|
|
448
465
|
};
|
|
@@ -459,12 +476,13 @@ function createDOMPurify() {
|
|
|
459
476
|
attribute: node.getAttributeNode(name),
|
|
460
477
|
from: node
|
|
461
478
|
});
|
|
462
|
-
} catch (
|
|
479
|
+
} catch (error) {
|
|
463
480
|
DOMPurify.removed.push({
|
|
464
481
|
attribute: null,
|
|
465
482
|
from: node
|
|
466
483
|
});
|
|
467
484
|
}
|
|
485
|
+
|
|
468
486
|
node.removeAttribute(name);
|
|
469
487
|
};
|
|
470
488
|
|
|
@@ -494,7 +512,7 @@ function createDOMPurify() {
|
|
|
494
512
|
if (useDOMParser) {
|
|
495
513
|
try {
|
|
496
514
|
doc = new DOMParser().parseFromString(dirty, 'text/html');
|
|
497
|
-
} catch (
|
|
515
|
+
} catch (error) {}
|
|
498
516
|
}
|
|
499
517
|
|
|
500
518
|
/* Remove title to fix a mXSS bug in older MS Edge */
|
|
@@ -537,15 +555,16 @@ function createDOMPurify() {
|
|
|
537
555
|
if (doc.querySelector('svg img')) {
|
|
538
556
|
useDOMParser = true;
|
|
539
557
|
}
|
|
540
|
-
} catch (
|
|
558
|
+
} catch (error) {}
|
|
541
559
|
})();
|
|
560
|
+
|
|
542
561
|
(function () {
|
|
543
562
|
try {
|
|
544
563
|
var doc = _initDocument('<x/><title></title><img>');
|
|
545
564
|
if (doc.querySelector('title').innerHTML.match(/<\/title/)) {
|
|
546
565
|
removeTitle = true;
|
|
547
566
|
}
|
|
548
|
-
} catch (
|
|
567
|
+
} catch (error) {}
|
|
549
568
|
})();
|
|
550
569
|
}
|
|
551
570
|
|
|
@@ -571,9 +590,11 @@ function createDOMPurify() {
|
|
|
571
590
|
if (elm instanceof Text || elm instanceof Comment) {
|
|
572
591
|
return false;
|
|
573
592
|
}
|
|
593
|
+
|
|
574
594
|
if (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function') {
|
|
575
595
|
return true;
|
|
576
596
|
}
|
|
597
|
+
|
|
577
598
|
return false;
|
|
578
599
|
};
|
|
579
600
|
|
|
@@ -615,6 +636,7 @@ function createDOMPurify() {
|
|
|
615
636
|
* @param {Node} currentNode to check for permission to exist
|
|
616
637
|
* @return {Boolean} true if node was killed, false if left alive
|
|
617
638
|
*/
|
|
639
|
+
// eslint-disable-next-line complexity
|
|
618
640
|
var _sanitizeElements = function _sanitizeElements(currentNode) {
|
|
619
641
|
var content = void 0;
|
|
620
642
|
|
|
@@ -643,8 +665,20 @@ function createDOMPurify() {
|
|
|
643
665
|
try {
|
|
644
666
|
var htmlToInsert = currentNode.innerHTML;
|
|
645
667
|
currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);
|
|
646
|
-
} catch (
|
|
668
|
+
} catch (error) {}
|
|
647
669
|
}
|
|
670
|
+
|
|
671
|
+
_forceRemove(currentNode);
|
|
672
|
+
return true;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/* Remove in case a noscript/noembed XSS is suspected */
|
|
676
|
+
if (tagName === 'noscript' && currentNode.innerHTML.match(/<\/noscript/i)) {
|
|
677
|
+
_forceRemove(currentNode);
|
|
678
|
+
return true;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
if (tagName === 'noembed' && currentNode.innerHTML.match(/<\/noembed/i)) {
|
|
648
682
|
_forceRemove(currentNode);
|
|
649
683
|
return true;
|
|
650
684
|
}
|
|
@@ -685,18 +719,13 @@ function createDOMPurify() {
|
|
|
685
719
|
* @param {string} value Attribute value.
|
|
686
720
|
* @return {Boolean} Returns true if `value` is valid, otherwise false.
|
|
687
721
|
*/
|
|
722
|
+
// eslint-disable-next-line complexity
|
|
688
723
|
var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
689
724
|
/* Make sure attribute cannot clobber */
|
|
690
725
|
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
691
726
|
return false;
|
|
692
727
|
}
|
|
693
728
|
|
|
694
|
-
/* Sanitize attribute content to be template-safe */
|
|
695
|
-
if (SAFE_FOR_TEMPLATES) {
|
|
696
|
-
value = value.replace(MUSTACHE_EXPR$$1, ' ');
|
|
697
|
-
value = value.replace(ERB_EXPR$$1, ' ');
|
|
698
|
-
}
|
|
699
|
-
|
|
700
729
|
/* Allow valid data-* attributes: At least one character after "-"
|
|
701
730
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
702
731
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
@@ -733,6 +762,7 @@ function createDOMPurify() {
|
|
|
733
762
|
} else {
|
|
734
763
|
return false;
|
|
735
764
|
}
|
|
765
|
+
|
|
736
766
|
return true;
|
|
737
767
|
};
|
|
738
768
|
|
|
@@ -744,9 +774,8 @@ function createDOMPurify() {
|
|
|
744
774
|
* @protect removeAttribute
|
|
745
775
|
* @protect setAttribute
|
|
746
776
|
*
|
|
747
|
-
* @param {Node}
|
|
777
|
+
* @param {Node} currentNode to sanitize
|
|
748
778
|
*/
|
|
749
|
-
// eslint-disable-next-line complexity
|
|
750
779
|
var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
751
780
|
var attr = void 0;
|
|
752
781
|
var value = void 0;
|
|
@@ -813,6 +842,7 @@ function createDOMPurify() {
|
|
|
813
842
|
if (name === 'id') {
|
|
814
843
|
currentNode.setAttribute(name, '');
|
|
815
844
|
}
|
|
845
|
+
|
|
816
846
|
_removeAttribute(name, currentNode);
|
|
817
847
|
}
|
|
818
848
|
|
|
@@ -821,6 +851,12 @@ function createDOMPurify() {
|
|
|
821
851
|
continue;
|
|
822
852
|
}
|
|
823
853
|
|
|
854
|
+
/* Sanitize attribute content to be template-safe */
|
|
855
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
856
|
+
value = value.replace(MUSTACHE_EXPR$$1, ' ');
|
|
857
|
+
value = value.replace(ERB_EXPR$$1, ' ');
|
|
858
|
+
}
|
|
859
|
+
|
|
824
860
|
/* Is `value` valid for this attribute? */
|
|
825
861
|
var lcTag = currentNode.nodeName.toLowerCase();
|
|
826
862
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
@@ -835,8 +871,9 @@ function createDOMPurify() {
|
|
|
835
871
|
/* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
|
|
836
872
|
currentNode.setAttribute(name, value);
|
|
837
873
|
}
|
|
874
|
+
|
|
838
875
|
DOMPurify.removed.pop();
|
|
839
|
-
} catch (
|
|
876
|
+
} catch (error) {}
|
|
840
877
|
}
|
|
841
878
|
|
|
842
879
|
/* Execute a hook if present */
|
|
@@ -917,10 +954,12 @@ function createDOMPurify() {
|
|
|
917
954
|
if (typeof dirty === 'string') {
|
|
918
955
|
return window.toStaticHTML(dirty);
|
|
919
956
|
}
|
|
957
|
+
|
|
920
958
|
if (_isNode(dirty)) {
|
|
921
959
|
return window.toStaticHTML(dirty.outerHTML);
|
|
922
960
|
}
|
|
923
961
|
}
|
|
962
|
+
|
|
924
963
|
return dirty;
|
|
925
964
|
}
|
|
926
965
|
|
|
@@ -943,11 +982,12 @@ function createDOMPurify() {
|
|
|
943
982
|
/* Node is already a body, use as is */
|
|
944
983
|
body = importedNode;
|
|
945
984
|
} else {
|
|
985
|
+
// eslint-disable-next-line unicorn/prefer-node-append
|
|
946
986
|
body.appendChild(importedNode);
|
|
947
987
|
}
|
|
948
988
|
} else {
|
|
949
989
|
/* Exit directly if we have nothing to do */
|
|
950
|
-
if (!RETURN_DOM && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
|
|
990
|
+
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
|
|
951
991
|
return trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
952
992
|
}
|
|
953
993
|
|
|
@@ -1004,6 +1044,7 @@ function createDOMPurify() {
|
|
|
1004
1044
|
returnNode = createDocumentFragment.call(body.ownerDocument);
|
|
1005
1045
|
|
|
1006
1046
|
while (body.firstChild) {
|
|
1047
|
+
// eslint-disable-next-line unicorn/prefer-node-append
|
|
1007
1048
|
returnNode.appendChild(body.firstChild);
|
|
1008
1049
|
}
|
|
1009
1050
|
} else {
|
|
@@ -1023,6 +1064,13 @@ function createDOMPurify() {
|
|
|
1023
1064
|
}
|
|
1024
1065
|
|
|
1025
1066
|
var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
|
1067
|
+
|
|
1068
|
+
/* Sanitize final string template-safe */
|
|
1069
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
1070
|
+
serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
|
|
1071
|
+
serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1026
1074
|
return trustedTypesPolicy ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
|
1027
1075
|
};
|
|
1028
1076
|
|
|
@@ -1062,6 +1110,7 @@ function createDOMPurify() {
|
|
|
1062
1110
|
if (!CONFIG) {
|
|
1063
1111
|
_parseConfig({});
|
|
1064
1112
|
}
|
|
1113
|
+
|
|
1065
1114
|
var lcTag = tag.toLowerCase();
|
|
1066
1115
|
var lcName = attr.toLowerCase();
|
|
1067
1116
|
return _isValidAttribute(lcTag, lcName, value);
|
|
@@ -1078,6 +1127,7 @@ function createDOMPurify() {
|
|
|
1078
1127
|
if (typeof hookFunction !== 'function') {
|
|
1079
1128
|
return;
|
|
1080
1129
|
}
|
|
1130
|
+
|
|
1081
1131
|
hooks[entryPoint] = hooks[entryPoint] || [];
|
|
1082
1132
|
hooks[entryPoint].push(hookFunction);
|
|
1083
1133
|
};
|