dompurify 2.2.4 → 2.2.8
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 +7 -2
- package/dist/purify.cjs.js +210 -34
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +210 -34
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +210 -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.2.
|
|
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.2.8.
|
|
10
10
|
|
|
11
11
|
DOMPurify is written in JavaScript and works in all modern browsers (Safari (10+), 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
|
|
|
@@ -160,6 +160,8 @@ var clean = DOMPurify.sanitize(dirty, {ALLOWED_TAGS: ['b']});
|
|
|
160
160
|
var clean = DOMPurify.sanitize(dirty, {ALLOWED_TAGS: ['b', 'q'], ALLOWED_ATTR: ['style']});
|
|
161
161
|
|
|
162
162
|
// allow all safe HTML elements but neither SVG nor MathML
|
|
163
|
+
// note that the USE_PROFILES setting will override the ALLOWED_TAGS setting
|
|
164
|
+
// so don't use them together
|
|
163
165
|
var clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {html: true}});
|
|
164
166
|
|
|
165
167
|
// allow all safe SVG elements and SVG Filters, no HTML or MathML
|
|
@@ -168,6 +170,9 @@ var clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {svg: true, svgFilters: tru
|
|
|
168
170
|
// allow all safe MathML elements and SVG, but no SVG Filters
|
|
169
171
|
var clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {mathMl: true, svg: true}});
|
|
170
172
|
|
|
173
|
+
// change the default namespace from HTML to something different
|
|
174
|
+
var clean = DOMPurify.sanitize(dirty, {NAMESPACE: 'http://www.w3.org/2000/svg'});
|
|
175
|
+
|
|
171
176
|
// leave all safe HTML as it is and add <style> elements to block-list
|
|
172
177
|
var clean = DOMPurify.sanitize(dirty, {FORBID_TAGS: ['style']});
|
|
173
178
|
|
|
@@ -332,7 +337,7 @@ Feature releases will not be announced to this list.
|
|
|
332
337
|
|
|
333
338
|
Many people helped and help DOMPurify become what it is and need to be acknowledged here!
|
|
334
339
|
|
|
335
|
-
[granlem 💸](https://twitter.com/MaximeVeit), [oreoshake 💸](https://github.com/oreoshake), [dcramer 💸](https://github.com/dcramer),[tdeekens ❤️](https://github.com/tdeekens), [peernohell ❤️](https://github.com/peernohell), [neilj](https://github.com/neilj), [fhemberger](https://github.com/fhemberger), [Joris-van-der-Wel](https://github.com/Joris-van-der-Wel), [ydaniv](https://github.com/ydaniv), [terjanq](https://twitter.com/terjanq), [filedescriptor](https://github.com/filedescriptor), [ConradIrwin](https://github.com/ConradIrwin), [gibson042](https://github.com/gibson042), [choumx](https://github.com/choumx), [0xSobky](https://github.com/0xSobky), [styfle](https://github.com/styfle), [koto](https://github.com/koto), [tlau88](https://github.com/tlau88), [strugee](https://github.com/strugee), [oparoz](https://github.com/oparoz), [mathiasbynens](https://github.com/mathiasbynens), [edg2s](https://github.com/edg2s), [dnkolegov](https://github.com/dnkolegov), [dhardtke](https://github.com/dhardtke), [wirehead](https://github.com/wirehead), [thorn0](https://github.com/thorn0), [styu](https://github.com/styu), [mozfreddyb](https://github.com/mozfreddyb), [mikesamuel](https://github.com/mikesamuel), [jorangreef](https://github.com/jorangreef), [jimmyhchan](https://github.com/jimmyhchan), [jameydeorio](https://github.com/jameydeorio), [jameskraus](https://github.com/jameskraus), [hyderali](https://github.com/hyderali), [hansottowirtz](https://github.com/hansottowirtz), [hackvertor](https://github.com/hackvertor), [freddyb](https://github.com/freddyb), [flavorjones](https://github.com/flavorjones), [djfarrelly](https://github.com/djfarrelly), [devd](https://github.com/devd), [camerondunford](https://github.com/camerondunford), [buu700](https://github.com/buu700), [buildog](https://github.com/buildog), [alabiaga](https://github.com/alabiaga), [Vector919](https://github.com/Vector919), [Robbert](https://github.com/Robbert), [GreLI](https://github.com/GreLI), [FuzzySockets](https://github.com/FuzzySockets), [ArtemBernatskyy](https://github.com/ArtemBernatskyy), [@garethheyes](https://twitter.com/garethheyes), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl),[ShikariSenpai](https://github.com/ShikariSenpai), [ansjdnakjdnajkd](https://github.com/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 [@securitymb ❤️](https://twitter.com/securitymb) & [@masatokinugawa ❤️](https://twitter.com/masatokinugawa)
|
|
340
|
+
[granlem 💸](https://twitter.com/MaximeVeit), [oreoshake 💸](https://github.com/oreoshake), [dcramer 💸](https://github.com/dcramer),[tdeekens ❤️](https://github.com/tdeekens), [peernohell ❤️](https://github.com/peernohell), [neilj](https://github.com/neilj), [fhemberger](https://github.com/fhemberger), [Joris-van-der-Wel](https://github.com/Joris-van-der-Wel), [ydaniv](https://github.com/ydaniv), [terjanq](https://twitter.com/terjanq), [filedescriptor](https://github.com/filedescriptor), [ConradIrwin](https://github.com/ConradIrwin), [gibson042](https://github.com/gibson042), [choumx](https://github.com/choumx), [0xSobky](https://github.com/0xSobky), [styfle](https://github.com/styfle), [koto](https://github.com/koto), [tlau88](https://github.com/tlau88), [strugee](https://github.com/strugee), [oparoz](https://github.com/oparoz), [mathiasbynens](https://github.com/mathiasbynens), [edg2s](https://github.com/edg2s), [dnkolegov](https://github.com/dnkolegov), [dhardtke](https://github.com/dhardtke), [wirehead](https://github.com/wirehead), [thorn0](https://github.com/thorn0), [styu](https://github.com/styu), [mozfreddyb](https://github.com/mozfreddyb), [mikesamuel](https://github.com/mikesamuel), [jorangreef](https://github.com/jorangreef), [jimmyhchan](https://github.com/jimmyhchan), [jameydeorio](https://github.com/jameydeorio), [jameskraus](https://github.com/jameskraus), [hyderali](https://github.com/hyderali), [hansottowirtz](https://github.com/hansottowirtz), [hackvertor](https://github.com/hackvertor), [freddyb](https://github.com/freddyb), [flavorjones](https://github.com/flavorjones), [djfarrelly](https://github.com/djfarrelly), [devd](https://github.com/devd), [camerondunford](https://github.com/camerondunford), [buu700](https://github.com/buu700), [buildog](https://github.com/buildog), [alabiaga](https://github.com/alabiaga), [Vector919](https://github.com/Vector919), [Robbert](https://github.com/Robbert), [GreLI](https://github.com/GreLI), [FuzzySockets](https://github.com/FuzzySockets), [ArtemBernatskyy](https://github.com/ArtemBernatskyy), [@garethheyes](https://twitter.com/garethheyes), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl),[ShikariSenpai](https://github.com/ShikariSenpai), [ansjdnakjdnajkd](https://github.com/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), [@CmdEngineer_](https://twitter.com/CmdEngineer_), [@avr4mit](https://twitter.com/avr4mit) and especially [@securitymb ❤️](https://twitter.com/securitymb) & [@masatokinugawa ❤️](https://twitter.com/masatokinugawa)
|
|
336
341
|
|
|
337
342
|
## Testing powered by
|
|
338
343
|
<a target="_blank" href="https://www.browserstack.com/"><img width="200" src="https://www.browserstack.com/images/layout/browserstack-logo-600x315.png"></a><br>
|
package/dist/purify.cjs.js
CHANGED
|
@@ -6,7 +6,9 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr
|
|
|
6
6
|
|
|
7
7
|
var hasOwnProperty = Object.hasOwnProperty,
|
|
8
8
|
setPrototypeOf = Object.setPrototypeOf,
|
|
9
|
-
isFrozen = Object.isFrozen
|
|
9
|
+
isFrozen = Object.isFrozen,
|
|
10
|
+
getPrototypeOf = Object.getPrototypeOf,
|
|
11
|
+
getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
10
12
|
var freeze = Object.freeze,
|
|
11
13
|
seal = Object.seal,
|
|
12
14
|
create = Object.create; // eslint-disable-line import/no-mutable-exports
|
|
@@ -117,18 +119,56 @@ function clone(object) {
|
|
|
117
119
|
return newObject;
|
|
118
120
|
}
|
|
119
121
|
|
|
122
|
+
/* IE10 doesn't support __lookupGetter__ so lets'
|
|
123
|
+
* simulate it. It also automatically checks
|
|
124
|
+
* if the prop is function or getter and behaves
|
|
125
|
+
* accordingly. */
|
|
126
|
+
function lookupGetter(object, prop) {
|
|
127
|
+
while (object !== null) {
|
|
128
|
+
var desc = getOwnPropertyDescriptor(object, prop);
|
|
129
|
+
if (desc) {
|
|
130
|
+
if (desc.get) {
|
|
131
|
+
return unapply(desc.get);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (typeof desc.value === 'function') {
|
|
135
|
+
return unapply(desc.value);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
object = getPrototypeOf(object);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function fallbackValue(element) {
|
|
143
|
+
console.warn('fallback value for', element);
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return fallbackValue;
|
|
148
|
+
}
|
|
149
|
+
|
|
120
150
|
var html = 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']);
|
|
121
151
|
|
|
122
152
|
// SVG
|
|
123
|
-
var svg = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', '
|
|
153
|
+
var svg = 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']);
|
|
124
154
|
|
|
125
155
|
var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
|
|
126
156
|
|
|
157
|
+
// List of SVG elements that are disallowed by default.
|
|
158
|
+
// We still need to know them so that we can do namespace
|
|
159
|
+
// checks properly in case one wants to add them to
|
|
160
|
+
// allow-list.
|
|
161
|
+
var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', 'feimage', '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']);
|
|
162
|
+
|
|
127
163
|
var mathMl = 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']);
|
|
128
164
|
|
|
165
|
+
// Similarly to SVG, we want to know all MathML elements,
|
|
166
|
+
// even those that we disallow by default.
|
|
167
|
+
var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
168
|
+
|
|
129
169
|
var text = freeze(['#text']);
|
|
130
170
|
|
|
131
|
-
var html$1 = 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', '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']);
|
|
171
|
+
var html$1 = 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', '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']);
|
|
132
172
|
|
|
133
173
|
var svg$1 = 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', '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']);
|
|
134
174
|
|
|
@@ -205,7 +245,7 @@ function createDOMPurify() {
|
|
|
205
245
|
* Version label, exposed for easier checks
|
|
206
246
|
* if DOMPurify is up to date or not
|
|
207
247
|
*/
|
|
208
|
-
DOMPurify.version = '2.2.
|
|
248
|
+
DOMPurify.version = '2.2.8';
|
|
209
249
|
|
|
210
250
|
/**
|
|
211
251
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -227,6 +267,7 @@ function createDOMPurify() {
|
|
|
227
267
|
var DocumentFragment = window.DocumentFragment,
|
|
228
268
|
HTMLTemplateElement = window.HTMLTemplateElement,
|
|
229
269
|
Node = window.Node,
|
|
270
|
+
Element = window.Element,
|
|
230
271
|
NodeFilter = window.NodeFilter,
|
|
231
272
|
_window$NamedNodeMap = window.NamedNodeMap,
|
|
232
273
|
NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
|
|
@@ -235,13 +276,20 @@ function createDOMPurify() {
|
|
|
235
276
|
DOMParser = window.DOMParser,
|
|
236
277
|
trustedTypes = window.trustedTypes;
|
|
237
278
|
|
|
279
|
+
|
|
280
|
+
var ElementPrototype = Element.prototype;
|
|
281
|
+
|
|
282
|
+
var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
|
|
283
|
+
var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
|
|
284
|
+
var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
|
|
285
|
+
var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
|
|
286
|
+
|
|
238
287
|
// As per issue #47, the web-components registry is inherited by a
|
|
239
288
|
// new document created via createHTMLDocument. As per the spec
|
|
240
289
|
// (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
|
|
241
290
|
// a new empty registry is used when creating a template contents owner
|
|
242
291
|
// document, so we use that as our parent document to ensure nothing
|
|
243
292
|
// is inherited.
|
|
244
|
-
|
|
245
293
|
if (typeof HTMLTemplateElement === 'function') {
|
|
246
294
|
var template = document.createElement('template');
|
|
247
295
|
if (template.content && template.content.ownerDocument) {
|
|
@@ -255,7 +303,6 @@ function createDOMPurify() {
|
|
|
255
303
|
var _document = document,
|
|
256
304
|
implementation = _document.implementation,
|
|
257
305
|
createNodeIterator = _document.createNodeIterator,
|
|
258
|
-
getElementsByTagName = _document.getElementsByTagName,
|
|
259
306
|
createDocumentFragment = _document.createDocumentFragment;
|
|
260
307
|
var importNode = originalDocument.importNode;
|
|
261
308
|
|
|
@@ -270,7 +317,7 @@ function createDOMPurify() {
|
|
|
270
317
|
/**
|
|
271
318
|
* Expose whether this browser supports running the full DOMPurify.
|
|
272
319
|
*/
|
|
273
|
-
DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
|
|
320
|
+
DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
|
|
274
321
|
|
|
275
322
|
var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
|
|
276
323
|
ERB_EXPR$$1 = ERB_EXPR,
|
|
@@ -363,7 +410,7 @@ function createDOMPurify() {
|
|
|
363
410
|
var USE_PROFILES = {};
|
|
364
411
|
|
|
365
412
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
366
|
-
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']);
|
|
413
|
+
var 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']);
|
|
367
414
|
|
|
368
415
|
/* Tags that are safe for data: URIs */
|
|
369
416
|
var DATA_URI_TAGS = null;
|
|
@@ -373,6 +420,12 @@ function createDOMPurify() {
|
|
|
373
420
|
var URI_SAFE_ATTRIBUTES = null;
|
|
374
421
|
var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
|
|
375
422
|
|
|
423
|
+
var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
|
|
424
|
+
var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
425
|
+
var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
|
|
426
|
+
/* Document namespace */
|
|
427
|
+
var NAMESPACE = HTML_NAMESPACE;
|
|
428
|
+
|
|
376
429
|
/* Keep a reference to config to pass to hooks */
|
|
377
430
|
var CONFIG = null;
|
|
378
431
|
|
|
@@ -422,6 +475,7 @@ function createDOMPurify() {
|
|
|
422
475
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
423
476
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
424
477
|
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
478
|
+
NAMESPACE = cfg.NAMESPACE || NAMESPACE;
|
|
425
479
|
if (SAFE_FOR_TEMPLATES) {
|
|
426
480
|
ALLOW_DATA_ATTR = false;
|
|
427
481
|
}
|
|
@@ -504,6 +558,111 @@ function createDOMPurify() {
|
|
|
504
558
|
CONFIG = cfg;
|
|
505
559
|
};
|
|
506
560
|
|
|
561
|
+
var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
|
|
562
|
+
|
|
563
|
+
var HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']);
|
|
564
|
+
|
|
565
|
+
/* Keep track of all possible SVG and MathML tags
|
|
566
|
+
* so that we can perform the namespace checks
|
|
567
|
+
* correctly. */
|
|
568
|
+
var ALL_SVG_TAGS = addToSet({}, svg);
|
|
569
|
+
addToSet(ALL_SVG_TAGS, svgFilters);
|
|
570
|
+
addToSet(ALL_SVG_TAGS, svgDisallowed);
|
|
571
|
+
|
|
572
|
+
var ALL_MATHML_TAGS = addToSet({}, mathMl);
|
|
573
|
+
addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
*
|
|
577
|
+
*
|
|
578
|
+
* @param {Element} element a DOM element whose namespace is being checked
|
|
579
|
+
* @returns {boolean} Return false if the element has a
|
|
580
|
+
* namespace that a spec-compliant parser would never
|
|
581
|
+
* return. Return true otherwise.
|
|
582
|
+
*/
|
|
583
|
+
var _checkValidNamespace = function _checkValidNamespace(element) {
|
|
584
|
+
var parent = getParentNode(element);
|
|
585
|
+
|
|
586
|
+
// In JSDOM, if we're inside shadow DOM, then parentNode
|
|
587
|
+
// can be null. We just simulate parent in this case.
|
|
588
|
+
if (!parent || !parent.tagName) {
|
|
589
|
+
parent = {
|
|
590
|
+
namespaceURI: HTML_NAMESPACE,
|
|
591
|
+
tagName: 'template'
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
var tagName = stringToLowerCase(element.tagName);
|
|
596
|
+
var parentTagName = stringToLowerCase(parent.tagName);
|
|
597
|
+
|
|
598
|
+
if (element.namespaceURI === SVG_NAMESPACE) {
|
|
599
|
+
// The only way to switch from HTML namespace to SVG
|
|
600
|
+
// is via <svg>. If it happens via any other tag, then
|
|
601
|
+
// it should be killed.
|
|
602
|
+
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
603
|
+
return tagName === 'svg';
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// The only way to switch from MathML to SVG is via
|
|
607
|
+
// svg if parent is either <annotation-xml> or MathML
|
|
608
|
+
// text integration points.
|
|
609
|
+
if (parent.namespaceURI === MATHML_NAMESPACE) {
|
|
610
|
+
return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// We only allow elements that are defined in SVG
|
|
614
|
+
// spec. All others are disallowed in SVG namespace.
|
|
615
|
+
return Boolean(ALL_SVG_TAGS[tagName]);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
if (element.namespaceURI === MATHML_NAMESPACE) {
|
|
619
|
+
// The only way to switch from HTML namespace to MathML
|
|
620
|
+
// is via <math>. If it happens via any other tag, then
|
|
621
|
+
// it should be killed.
|
|
622
|
+
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
623
|
+
return tagName === 'math';
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// The only way to switch from SVG to MathML is via
|
|
627
|
+
// <math> and HTML integration points
|
|
628
|
+
if (parent.namespaceURI === SVG_NAMESPACE) {
|
|
629
|
+
return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// We only allow elements that are defined in MathML
|
|
633
|
+
// spec. All others are disallowed in MathML namespace.
|
|
634
|
+
return Boolean(ALL_MATHML_TAGS[tagName]);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (element.namespaceURI === HTML_NAMESPACE) {
|
|
638
|
+
// The only way to switch from SVG to HTML is via
|
|
639
|
+
// HTML integration points, and from MathML to HTML
|
|
640
|
+
// is via MathML text integration points
|
|
641
|
+
if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
|
|
642
|
+
return false;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// Certain elements are allowed in both SVG and HTML
|
|
650
|
+
// namespace. We need to specify them explicitly
|
|
651
|
+
// so that they don't get erronously deleted from
|
|
652
|
+
// HTML namespace.
|
|
653
|
+
var commonSvgAndHTMLElements = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
|
|
654
|
+
|
|
655
|
+
// We disallow tags that are specific for MathML
|
|
656
|
+
// or SVG and should never appear in HTML namespace
|
|
657
|
+
return !ALL_MATHML_TAGS[tagName] && (commonSvgAndHTMLElements[tagName] || !ALL_SVG_TAGS[tagName]);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// The code should never reach this place (this means
|
|
661
|
+
// that the element somehow got namespace that is not
|
|
662
|
+
// HTML, SVG or MathML). Return false just in case.
|
|
663
|
+
return false;
|
|
664
|
+
};
|
|
665
|
+
|
|
507
666
|
/**
|
|
508
667
|
* _forceRemove
|
|
509
668
|
*
|
|
@@ -542,6 +701,19 @@ function createDOMPurify() {
|
|
|
542
701
|
}
|
|
543
702
|
|
|
544
703
|
node.removeAttribute(name);
|
|
704
|
+
|
|
705
|
+
// We void attribute values for unremovable "is"" attributes
|
|
706
|
+
if (name === 'is' && !ALLOWED_ATTR[name]) {
|
|
707
|
+
if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
|
|
708
|
+
try {
|
|
709
|
+
_forceRemove(node);
|
|
710
|
+
} catch (_) {}
|
|
711
|
+
} else {
|
|
712
|
+
try {
|
|
713
|
+
node.setAttribute(name, '');
|
|
714
|
+
} catch (_) {}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
545
717
|
};
|
|
546
718
|
|
|
547
719
|
/**
|
|
@@ -564,27 +736,30 @@ function createDOMPurify() {
|
|
|
564
736
|
}
|
|
565
737
|
|
|
566
738
|
var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
567
|
-
/*
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
739
|
+
/*
|
|
740
|
+
* Use the DOMParser API by default, fallback later if needs be
|
|
741
|
+
* DOMParser not work for svg when has multiple root element.
|
|
742
|
+
*/
|
|
743
|
+
if (NAMESPACE === HTML_NAMESPACE) {
|
|
744
|
+
try {
|
|
745
|
+
doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
|
|
746
|
+
} catch (_) {}
|
|
747
|
+
}
|
|
571
748
|
|
|
572
749
|
/* Use createHTMLDocument in case DOMParser is not available */
|
|
573
750
|
if (!doc || !doc.documentElement) {
|
|
574
|
-
doc = implementation.
|
|
575
|
-
|
|
576
|
-
body = _doc.body;
|
|
577
|
-
|
|
578
|
-
body.parentNode.removeChild(body.parentNode.firstElementChild);
|
|
579
|
-
body.outerHTML = dirtyPayload;
|
|
751
|
+
doc = implementation.createDocument(NAMESPACE, 'template', null);
|
|
752
|
+
doc.documentElement.innerHTML = dirtyPayload;
|
|
580
753
|
}
|
|
581
754
|
|
|
755
|
+
var body = doc.body || doc.documentElement;
|
|
756
|
+
|
|
582
757
|
if (dirty && leadingWhitespace) {
|
|
583
|
-
|
|
758
|
+
body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
|
|
584
759
|
}
|
|
585
760
|
|
|
586
761
|
/* Work on whole document or just its body */
|
|
587
|
-
return
|
|
762
|
+
return WHOLE_DOCUMENT ? doc.documentElement : body;
|
|
588
763
|
};
|
|
589
764
|
|
|
590
765
|
/**
|
|
@@ -610,7 +785,7 @@ function createDOMPurify() {
|
|
|
610
785
|
return false;
|
|
611
786
|
}
|
|
612
787
|
|
|
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' || typeof elm.namespaceURI !== 'string') {
|
|
788
|
+
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' || typeof elm.insertBefore !== 'function') {
|
|
614
789
|
return true;
|
|
615
790
|
}
|
|
616
791
|
|
|
@@ -691,29 +866,30 @@ function createDOMPurify() {
|
|
|
691
866
|
/* Remove element if anything forbids its presence */
|
|
692
867
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
693
868
|
/* Keep content except for bad-listed elements */
|
|
694
|
-
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);
|
|
698
|
-
} catch (_) {}
|
|
699
|
-
}
|
|
869
|
+
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
870
|
+
var parentNode = getParentNode(currentNode) || currentNode.parentNode;
|
|
871
|
+
var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
|
|
700
872
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
873
|
+
if (childNodes && parentNode) {
|
|
874
|
+
var childCount = childNodes.length;
|
|
875
|
+
|
|
876
|
+
for (var i = childCount - 1; i >= 0; --i) {
|
|
877
|
+
parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
704
881
|
|
|
705
|
-
if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
|
|
706
882
|
_forceRemove(currentNode);
|
|
707
883
|
return true;
|
|
708
884
|
}
|
|
709
885
|
|
|
710
|
-
|
|
886
|
+
/* Check whether element has a valid namespace */
|
|
887
|
+
if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
|
|
711
888
|
_forceRemove(currentNode);
|
|
712
889
|
return true;
|
|
713
890
|
}
|
|
714
891
|
|
|
715
|
-
|
|
716
|
-
if (tagName === 'svg' && currentNode.querySelectorAll('p, br, table, form, noscript').length > 0) {
|
|
892
|
+
if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
|
|
717
893
|
_forceRemove(currentNode);
|
|
718
894
|
return true;
|
|
719
895
|
}
|