dompurify 2.0.3 → 2.0.7
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 -12
- package/dist/purify.cjs.js +20 -34
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +20 -34
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +20 -34
- 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 +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
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 2.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 2.0.7.
|
|
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
|
|
|
@@ -83,9 +83,11 @@ const clean = DOMPurify.sanitize(dirty);
|
|
|
83
83
|
|
|
84
84
|
Of course there is a demo! [Play with DOMPurify](https://cure53.de/purify)
|
|
85
85
|
|
|
86
|
-
## What if I find a
|
|
86
|
+
## What if I find a _security_ bug?
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
First of all, please immediately contact us via [email](mailto:mario@cure53.de) so we can work on a fix. [PGP key](https://keyserver.ubuntu.com/pks/lookup?op=vindex&search=0xC26C858090F70ADA)
|
|
89
|
+
|
|
90
|
+
Also, you probably qualify for a bug bounty! The fine folks over at [FastMail](https://www.fastmail.com/) use DOMPurify for their services and added our library to their bug bounty scope. So, if you find a way to bypass or weaken DOMPurify, please also have a look at their website and the [bug bounty info](https://www.fastmail.com/about/bugbounty.html).
|
|
89
91
|
|
|
90
92
|
## Some purification samples please?
|
|
91
93
|
|
|
@@ -278,14 +280,8 @@ Feature releases will not be announced to this list.
|
|
|
278
280
|
|
|
279
281
|
## Who contributed?
|
|
280
282
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
[@garethheyes](https://twitter.com/garethheyes) and [@filedescriptor](https://twitter.com/filedescriptor) for invaluable help, [@shafigullin](https://twitter.com/shafigullin) for breaking the library multiple times and thereby strengthening it in the early days, [@mmrupp](https://twitter.com/mmrupp) and [@irsdl](https://twitter.com/irsdl) for doing the same. And lastly, thanks to @ShikariSenpai and @ansjdnakjdnajkd for spotting a [massive Safari 10.1 bug](https://github.com/cure53/DOMPurify/releases/tag/0.8.6) early on and reporting it.
|
|
284
|
-
|
|
285
|
-
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)! Further, we would like to thank @masatokinugawa for his continuous and extremely valuable help in the past and present.
|
|
286
|
-
|
|
287
|
-
Further, thanks [@neilj](https://twitter.com/neilj) and [@0xsobky](https://twitter.com/0xsobky) for their early 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.
|
|
283
|
+
Many people helped DOMPurify become what it is and need to be acknowledged here!
|
|
288
284
|
|
|
289
|
-
|
|
285
|
+
@tdeekens, @neilj, @fhemberger, @Joris-van-der-Wel, @ydaniv, @filedescriptor, @ConradIrwin, @gibson042, @choumx, @0xSobky, @styfle, @koto, @tlau88, @strugee, @oparoz, @mathiasbynens, @edg2s, @dnkolegov, @dhardtke, @wirehead, @thorn0, @styu, @mozfreddyb, @mikesamuel, @jorangreef, @jimmyhchan, @jameydeorio, @jameskraus, @hyderali, @hansottowirtz, @hackvertor, @freddyb, @flavorjones, @djfarrelly, @devd, @camerondunford, @buu700, @buildog, @alabiaga, @Vector919, @Robbert, @GreLI, @FuzzySockets, @ArtemBernatskyy, [@garethheyes](https://twitter.com/garethheyes), [@filedescriptor](https://twitter.com/filedescriptor), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl), @ShikariSenpai, @ansjdnakjdnajkd, [@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 especially @masatokinugawa
|
|
290
286
|
|
|
291
|
-
And last but not least, thanks to [BrowserStack](https://browserstack.com) for supporting this project with their services for free and delivering excellent, dedicated and very professional support on top of that.
|
|
287
|
+
And last but not least, thanks to [BrowserStack](https://browserstack.com) for supporting this project with their services for free and delivering excellent, dedicated and very professional support on top of that.
|
package/dist/purify.cjs.js
CHANGED
|
@@ -23,7 +23,7 @@ var html$1 = freeze$2(['accept', 'action', 'align', 'alt', 'autocomplete', 'back
|
|
|
23
23
|
|
|
24
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', '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', '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
|
-
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']);
|
|
26
|
+
var mathMl$1 = freeze$2(['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']);
|
|
27
27
|
|
|
28
28
|
var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
29
29
|
|
|
@@ -167,7 +167,7 @@ function createDOMPurify() {
|
|
|
167
167
|
* Version label, exposed for easier checks
|
|
168
168
|
* if DOMPurify is up to date or not
|
|
169
169
|
*/
|
|
170
|
-
DOMPurify.version = '2.0.
|
|
170
|
+
DOMPurify.version = '2.0.7';
|
|
171
171
|
|
|
172
172
|
/**
|
|
173
173
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -185,7 +185,6 @@ function createDOMPurify() {
|
|
|
185
185
|
|
|
186
186
|
var originalDocument = window.document;
|
|
187
187
|
var useDOMParser = false;
|
|
188
|
-
var removeSVGAttr = false;
|
|
189
188
|
var removeTitle = false;
|
|
190
189
|
|
|
191
190
|
var document = window.document;
|
|
@@ -321,7 +320,7 @@ function createDOMPurify() {
|
|
|
321
320
|
var USE_PROFILES = {};
|
|
322
321
|
|
|
323
322
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
324
|
-
var FORBID_CONTENTS = addToSet({}, ['audio', 'colgroup', 'head', 'math', 'script', 'style', 'template', 'thead', '
|
|
323
|
+
var FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
|
|
325
324
|
|
|
326
325
|
/* Tags that are safe for data: URIs */
|
|
327
326
|
var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
|
|
@@ -541,7 +540,7 @@ function createDOMPurify() {
|
|
|
541
540
|
body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
542
541
|
}
|
|
543
542
|
|
|
544
|
-
if (leadingWhitespace) {
|
|
543
|
+
if (dirty && leadingWhitespace) {
|
|
545
544
|
doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
|
|
546
545
|
}
|
|
547
546
|
|
|
@@ -571,20 +570,11 @@ function createDOMPurify() {
|
|
|
571
570
|
(function () {
|
|
572
571
|
try {
|
|
573
572
|
var doc = _initDocument('<x/><title></title><img>');
|
|
574
|
-
if (doc.querySelector('title').innerHTML
|
|
573
|
+
if (/<\/title/.test(doc.querySelector('title').innerHTML)) {
|
|
575
574
|
removeTitle = true;
|
|
576
575
|
}
|
|
577
576
|
} catch (error) {}
|
|
578
577
|
})();
|
|
579
|
-
|
|
580
|
-
(function () {
|
|
581
|
-
try {
|
|
582
|
-
var doc = _initDocument('<svg></p></svg>');
|
|
583
|
-
if (doc.querySelector('svg p')) {
|
|
584
|
-
removeSVGAttr = true;
|
|
585
|
-
}
|
|
586
|
-
} catch (error) {}
|
|
587
|
-
})();
|
|
588
578
|
}
|
|
589
579
|
|
|
590
580
|
/**
|
|
@@ -610,7 +600,7 @@ function createDOMPurify() {
|
|
|
610
600
|
return false;
|
|
611
601
|
}
|
|
612
602
|
|
|
613
|
-
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') {
|
|
603
|
+
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' || typeof elm.namespaceURI !== 'string') {
|
|
614
604
|
return true;
|
|
615
605
|
}
|
|
616
606
|
|
|
@@ -677,6 +667,12 @@ function createDOMPurify() {
|
|
|
677
667
|
allowedTags: ALLOWED_TAGS
|
|
678
668
|
});
|
|
679
669
|
|
|
670
|
+
/* Take care of an mXSS pattern using p, br inside svg, math */
|
|
671
|
+
if ((tagName === 'svg' || tagName === 'math') && currentNode.querySelectorAll('p, br').length !== 0) {
|
|
672
|
+
_forceRemove(currentNode);
|
|
673
|
+
return true;
|
|
674
|
+
}
|
|
675
|
+
|
|
680
676
|
/* Remove element if anything forbids its presence */
|
|
681
677
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
682
678
|
/* Keep content except for black-listed elements */
|
|
@@ -692,23 +688,12 @@ function createDOMPurify() {
|
|
|
692
688
|
}
|
|
693
689
|
|
|
694
690
|
/* Remove in case a noscript/noembed XSS is suspected */
|
|
695
|
-
if (tagName === 'noscript' &&
|
|
696
|
-
_forceRemove(currentNode);
|
|
697
|
-
return true;
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
if (tagName === 'noembed' && currentNode.innerHTML.match(/<\/noembed/i)) {
|
|
701
|
-
_forceRemove(currentNode);
|
|
702
|
-
return true;
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
/* Remove in case an mXSS is suspected */
|
|
706
|
-
if (currentNode.namespaceURI && currentNode.namespaceURI.match(/svg|math/i) && currentNode.textContent && currentNode.textContent.match(new RegExp('</' + tagName, 'i'))) {
|
|
691
|
+
if (tagName === 'noscript' && /<\/noscript/i.test(currentNode.innerHTML)) {
|
|
707
692
|
_forceRemove(currentNode);
|
|
708
693
|
return true;
|
|
709
694
|
}
|
|
710
695
|
|
|
711
|
-
if (
|
|
696
|
+
if (tagName === 'noembed' && /<\/noembed/i.test(currentNode.innerHTML)) {
|
|
712
697
|
_forceRemove(currentNode);
|
|
713
698
|
return true;
|
|
714
699
|
}
|
|
@@ -849,11 +834,6 @@ function createDOMPurify() {
|
|
|
849
834
|
_executeHook('uponSanitizeAttribute', currentNode, hookEvent);
|
|
850
835
|
value = hookEvent.attrValue;
|
|
851
836
|
|
|
852
|
-
/* Check for possible Chrome mXSS */
|
|
853
|
-
if (removeSVGAttr && value.match(/<\//)) {
|
|
854
|
-
_forceRemove(currentNode);
|
|
855
|
-
}
|
|
856
|
-
|
|
857
837
|
/* Remove attribute */
|
|
858
838
|
// Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
|
|
859
839
|
// remove a "name" attribute from an <img> tag that has an "id"
|
|
@@ -887,6 +867,12 @@ function createDOMPurify() {
|
|
|
887
867
|
continue;
|
|
888
868
|
}
|
|
889
869
|
|
|
870
|
+
/* Take care of an mXSS pattern using namespace switches */
|
|
871
|
+
if (/svg|math/i.test(currentNode.namespaceURI) && new RegExp('</(' + Object.keys(FORBID_CONTENTS).join('|') + ')', 'i').test(value)) {
|
|
872
|
+
_removeAttribute(name, currentNode);
|
|
873
|
+
continue;
|
|
874
|
+
}
|
|
875
|
+
|
|
890
876
|
/* Sanitize attribute content to be template-safe */
|
|
891
877
|
if (SAFE_FOR_TEMPLATES) {
|
|
892
878
|
value = value.replace(MUSTACHE_EXPR$$1, ' ');
|