dompurify 2.3.2 → 2.3.6
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 +73 -31
- package/dist/purify.cjs.js +102 -37
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +102 -37
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +102 -37
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +2 -2
- package/dist/purify.min.js.map +1 -1
- package/package.json +10 -15
package/README.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# DOMPurify
|
|
2
2
|
|
|
3
|
-
[](http://badge.fury.io/js/dompurify)
|
|
3
|
+
[](http://badge.fury.io/js/dompurify)  [](https://www.npmjs.com/package/dompurify) [](https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js) [](https://packagephobia.now.sh/result?p=dompurify) [](https://github.com/cure53/DOMPurify/network/dependents)
|
|
4
4
|
|
|
5
5
|
[](https://nodei.co/npm/dompurify/)
|
|
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.3.
|
|
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.3.6.
|
|
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
|
|
|
13
|
-
Our automated tests cover [
|
|
13
|
+
Our automated tests cover [19 different browsers](https://github.com/cure53/DOMPurify/blob/main/test/karma.custom-launchers.config.js#L5) right now, more to come. We also cover Node.js v14.15.1, v15.4.0, v16.13.0, v17.0.0, running DOMPurify on [jsdom](https://github.com/tmpvar/jsdom). Older Node.js versions are known to work as well.
|
|
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
|
|
|
@@ -37,14 +37,14 @@ It's easy. Just include DOMPurify on your website.
|
|
|
37
37
|
Afterwards you can sanitize strings by executing the following code:
|
|
38
38
|
|
|
39
39
|
```js
|
|
40
|
-
let clean = DOMPurify.sanitize(
|
|
40
|
+
let clean = DOMPurify.sanitize(dirty);
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
The resulting HTML can be written into a DOM element using `innerHTML` or the DOM using `document.write()`. That is fully up to you.
|
|
43
|
+
The resulting HTML can be written into a DOM element using `innerHTML` or the DOM using `document.write()`. That is fully up to you.
|
|
44
44
|
Note that by default, we permit HTML, SVG **and** MathML. If you only need HTML, which might be a very common use-case, you can easily set that up as well:
|
|
45
45
|
|
|
46
46
|
```js
|
|
47
|
-
let clean = DOMPurify.sanitize(
|
|
47
|
+
let clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
### Is there any foot-gun potential?
|
|
@@ -133,7 +133,7 @@ DOMPurify also exposes a property called `isSupported`, which tells you whether
|
|
|
133
133
|
In version 1.0.9, support for [Trusted Types API](https://github.com/WICG/trusted-types) was added to DOMPurify.
|
|
134
134
|
In version 2.0.0, a config flag was added to control DOMPurify's behavior regarding this.
|
|
135
135
|
|
|
136
|
-
When `DOMPurify.sanitize` is used in an environment where the Trusted Types API is available and `RETURN_TRUSTED_TYPE` is set to `true`, it tries to return a `TrustedHTML` value instead of a string (the behavior for `RETURN_DOM
|
|
136
|
+
When `DOMPurify.sanitize` is used in an environment where the Trusted Types API is available and `RETURN_TRUSTED_TYPE` is set to `true`, it tries to return a `TrustedHTML` value instead of a string (the behavior for `RETURN_DOM` and `RETURN_DOM_FRAGMENT` config options does not change).
|
|
137
137
|
|
|
138
138
|
## Can I configure DOMPurify?
|
|
139
139
|
|
|
@@ -185,9 +185,58 @@ var clean = DOMPurify.sanitize(dirty, {ADD_TAGS: ['my-tag']});
|
|
|
185
185
|
// extend the existing array of allowed attributes and add my-attr to allow-list
|
|
186
186
|
var clean = DOMPurify.sanitize(dirty, {ADD_ATTR: ['my-attr']});
|
|
187
187
|
|
|
188
|
+
// prohibit ARIA attributes, leave other safe HTML as is (default is true)
|
|
189
|
+
var clean = DOMPurify.sanitize(dirty, {ALLOW_ARIA_ATTR: false});
|
|
190
|
+
|
|
188
191
|
// prohibit HTML5 data attributes, leave other safe HTML as is (default is true)
|
|
189
192
|
var clean = DOMPurify.sanitize(dirty, {ALLOW_DATA_ATTR: false});
|
|
190
193
|
|
|
194
|
+
/**
|
|
195
|
+
* Control behavior relating to Custom Elements
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
// DOMPurify allows to define rules for Custom Elements. When using the CUSTOM_ELEMENT_HANDLING
|
|
199
|
+
// literal, it is possible to define exactly what elements you wish to allow (by default, none are allowed).
|
|
200
|
+
//
|
|
201
|
+
// The same goes for their attributes. By default, the built-in or configured allow.list is used.
|
|
202
|
+
//
|
|
203
|
+
// You can use a RegExp literal to specify what is allowed or a predicate, examples for both can be seen below.
|
|
204
|
+
// The default values are very restrictive to prevent accidental XSS bypasses. Handle with great care!
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
var clean = DOMPurify.sanitize(
|
|
208
|
+
'<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
|
|
209
|
+
{
|
|
210
|
+
CUSTOM_ELEMENT_HANDLING: {
|
|
211
|
+
tagNameCheck: null, // no custom elements are allowed
|
|
212
|
+
attributeNameCheck: null, // default / standard attribute allow-list is used
|
|
213
|
+
allowCustomizedBuiltInElements: false, // no customized built-ins allowed
|
|
214
|
+
},
|
|
215
|
+
}
|
|
216
|
+
); // <div is=""></div>
|
|
217
|
+
|
|
218
|
+
var clean = DOMPurify.sanitize(
|
|
219
|
+
'<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
|
|
220
|
+
{
|
|
221
|
+
CUSTOM_ELEMENT_HANDLING: {
|
|
222
|
+
tagNameCheck: /^foo-/, // allow all tags starting with "foo-"
|
|
223
|
+
attributeNameCheck: /baz/, // allow all attributes containing "baz"
|
|
224
|
+
allowCustomizedBuiltInElements: false, // customized built-ins are allowed
|
|
225
|
+
},
|
|
226
|
+
}
|
|
227
|
+
); // <foo-bar baz="foobar"></foo-bar><div is=""></div>
|
|
228
|
+
|
|
229
|
+
var clean = DOMPurify.sanitize(
|
|
230
|
+
'<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
|
|
231
|
+
{
|
|
232
|
+
CUSTOM_ELEMENT_HANDLING: {
|
|
233
|
+
tagNameCheck: (tagName) => tagName.match(/^foo-/), // allow all tags starting with "foo-"
|
|
234
|
+
attributeNameCheck: (attr) => attr.match(/baz/), // allow all containing "baz"
|
|
235
|
+
allowCustomizedBuiltInElements: true, // allow customized built-ins
|
|
236
|
+
},
|
|
237
|
+
}
|
|
238
|
+
); // <foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>
|
|
239
|
+
|
|
191
240
|
/**
|
|
192
241
|
* Control behavior relating to URI values
|
|
193
242
|
*/
|
|
@@ -211,9 +260,6 @@ var clean = DOMPurify.sanitize(dirty, {ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|
|
|
|
211
260
|
|
|
212
261
|
/**
|
|
213
262
|
* Influence the return-type
|
|
214
|
-
*
|
|
215
|
-
* Careful, this setting has foot-gun potential! If you set RETURN_DOM or RETURN_DOM_FRAGMENT to true, don't set RETURN_DOM_IMPORT to false!
|
|
216
|
-
* By default, our settings are secure - we believe - but returning a DOM *and* manually setting RETURN_DOM_IMPORT to false will give you XSS in some situations.
|
|
217
263
|
*/
|
|
218
264
|
// return a DOM HTMLBodyElement instead of an HTML string (default is false)
|
|
219
265
|
var clean = DOMPurify.sanitize(dirty, {RETURN_DOM: true});
|
|
@@ -221,13 +267,6 @@ var clean = DOMPurify.sanitize(dirty, {RETURN_DOM: true});
|
|
|
221
267
|
// return a DOM DocumentFragment instead of an HTML string (default is false)
|
|
222
268
|
var clean = DOMPurify.sanitize(dirty, {RETURN_DOM_FRAGMENT: true});
|
|
223
269
|
|
|
224
|
-
// return a DOM DocumentFragment instead of an HTML string (default is false)
|
|
225
|
-
// also import it into the current document (default is false).
|
|
226
|
-
// RETURN_DOM_IMPORT must be set if you would like to append
|
|
227
|
-
// the returned node to the current document (default is true)
|
|
228
|
-
var clean = DOMPurify.sanitize(dirty, {RETURN_DOM_FRAGMENT: true, RETURN_DOM_IMPORT: true});
|
|
229
|
-
document.body.appendChild(clean);
|
|
230
|
-
|
|
231
270
|
// use the RETURN_TRUSTED_TYPE flag to turn on Trusted Types support if available
|
|
232
271
|
var clean = DOMPurify.sanitize(dirty, {RETURN_TRUSTED_TYPE: true}); // will return a TrustedHTML object instead of a string if possible
|
|
233
272
|
|
|
@@ -246,6 +285,9 @@ var clean = DOMPurify.sanitize(dirty, {KEEP_CONTENT: false});
|
|
|
246
285
|
// glue elements like style, script or others to document.body and prevent unintuitive browser behavior in several edge-cases (default is false)
|
|
247
286
|
var clean = DOMPurify.sanitize(dirty, {FORCE_BODY: true});
|
|
248
287
|
|
|
288
|
+
// change the parser type so sanitized data is treated as XML and not as HTML, which is the default
|
|
289
|
+
var clean = DOMPurify.sanitize(dirty, {PARSER_MEDIA_TYPE: 'application/xhtml+xml'});
|
|
290
|
+
|
|
249
291
|
/**
|
|
250
292
|
* Influence where we sanitize
|
|
251
293
|
*/
|
|
@@ -280,15 +322,14 @@ It passes the currently processed DOM node, when needed a literal with verified
|
|
|
280
322
|
_Example_:
|
|
281
323
|
|
|
282
324
|
```js
|
|
283
|
-
DOMPurify.addHook(
|
|
284
|
-
|
|
285
|
-
hookEvent,
|
|
286
|
-
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
});
|
|
325
|
+
DOMPurify.addHook(
|
|
326
|
+
'beforeSanitizeElements',
|
|
327
|
+
function (currentNode, hookEvent, config) {
|
|
328
|
+
// Do something with the current node and return it
|
|
329
|
+
// You can also mutate hookEvent (i.e. set hookEvent.forceKeepAttr = true)
|
|
330
|
+
return currentNode;
|
|
331
|
+
}
|
|
332
|
+
);
|
|
292
333
|
```
|
|
293
334
|
|
|
294
335
|
## Continuous Integration
|
|
@@ -301,9 +342,9 @@ All relevant commits will be signed with the key `0x24BB6BF4` for additional sec
|
|
|
301
342
|
|
|
302
343
|
### Development and contributing
|
|
303
344
|
|
|
304
|
-
#### Installation (`
|
|
345
|
+
#### Installation (`npm i`)
|
|
305
346
|
|
|
306
|
-
We support
|
|
347
|
+
We support `npm` officially. GitHub Actions workflow is configured to install dependencies using `npm`. When using deprected version of `npm` we can not fully ensure the versions of installed dependencies which might lead to unanticipated problems.
|
|
307
348
|
|
|
308
349
|
#### Scripts
|
|
309
350
|
|
|
@@ -321,7 +362,7 @@ These are our npm scripts:
|
|
|
321
362
|
- `npm run build:umd` to only build an unminified UMD module
|
|
322
363
|
- `npm run build:umd:min` to only build a minified UMD module
|
|
323
364
|
|
|
324
|
-
Note: all run scripts triggered via `npm run <script
|
|
365
|
+
Note: all run scripts triggered via `npm run <script>`.
|
|
325
366
|
|
|
326
367
|
There are more npm scripts but they are mainly to integrate with CI or are meant to be "private" for instance to amend build distribution files with every commit.
|
|
327
368
|
|
|
@@ -337,9 +378,10 @@ Feature releases will not be announced to this list.
|
|
|
337
378
|
|
|
338
379
|
Many people helped and help DOMPurify become what it is and need to be acknowledged here!
|
|
339
380
|
|
|
340
|
-
[lowdefy 💸](https://twitter.com/lowdefy), [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), [NateScarlet](https://github.com/NateScarlet), [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), [@
|
|
381
|
+
[jarrodldavis 💸](https://github.com/jarrodldavis), [GrantGryczan 💸](https://github.com/GrantGryczan), [lowdefy 💸](https://twitter.com/lowdefy), [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), [is2ei](https://github.com/is2ei), [franktopel](https://github.com/franktopel), [NateScarlet](https://github.com/NateScarlet), [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)
|
|
382
|
+
|
|
383
|
+
## Testing powered by
|
|
341
384
|
|
|
342
|
-
## Testing powered by
|
|
343
385
|
<a target="_blank" href="https://www.browserstack.com/"><img width="200" src="https://www.browserstack.com/images/layout/browserstack-logo-600x315.png"></a><br>
|
|
344
386
|
|
|
345
387
|
And last but not least, thanks to [BrowserStack Open-Source Program](https://www.browserstack.com/open-source) 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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @license DOMPurify 2.3.
|
|
1
|
+
/*! @license DOMPurify 2.3.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.6/LICENSE */
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
@@ -152,13 +152,13 @@ var html = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside'
|
|
|
152
152
|
// SVG
|
|
153
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']);
|
|
154
154
|
|
|
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']);
|
|
155
|
+
var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
|
|
156
156
|
|
|
157
157
|
// List of SVG elements that are disallowed by default.
|
|
158
158
|
// We still need to know them so that we can do namespace
|
|
159
159
|
// checks properly in case one wants to add them to
|
|
160
160
|
// allow-list.
|
|
161
|
-
var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', '
|
|
161
|
+
var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);
|
|
162
162
|
|
|
163
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']);
|
|
164
164
|
|
|
@@ -168,9 +168,9 @@ var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv
|
|
|
168
168
|
|
|
169
169
|
var text = freeze(['#text']);
|
|
170
170
|
|
|
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']);
|
|
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', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns', 'slot']);
|
|
172
172
|
|
|
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']);
|
|
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', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
|
|
174
174
|
|
|
175
175
|
var mathMl$1 = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
|
|
176
176
|
|
|
@@ -186,6 +186,7 @@ var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-
|
|
|
186
186
|
var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
|
|
187
187
|
var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
|
|
188
188
|
);
|
|
189
|
+
var DOCTYPE_NAME = seal(/^html$/i);
|
|
189
190
|
|
|
190
191
|
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; };
|
|
191
192
|
|
|
@@ -245,7 +246,7 @@ function createDOMPurify() {
|
|
|
245
246
|
* Version label, exposed for easier checks
|
|
246
247
|
* if DOMPurify is up to date or not
|
|
247
248
|
*/
|
|
248
|
-
DOMPurify.version = '2.3.
|
|
249
|
+
DOMPurify.version = '2.3.6';
|
|
249
250
|
|
|
250
251
|
/**
|
|
251
252
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -271,8 +272,7 @@ function createDOMPurify() {
|
|
|
271
272
|
NodeFilter = window.NodeFilter,
|
|
272
273
|
_window$NamedNodeMap = window.NamedNodeMap,
|
|
273
274
|
NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
|
|
274
|
-
|
|
275
|
-
Comment = window.Comment,
|
|
275
|
+
HTMLFormElement = window.HTMLFormElement,
|
|
276
276
|
DOMParser = window.DOMParser,
|
|
277
277
|
trustedTypes = window.trustedTypes;
|
|
278
278
|
|
|
@@ -298,7 +298,7 @@ function createDOMPurify() {
|
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
|
|
301
|
-
var emptyHTML = trustedTypesPolicy
|
|
301
|
+
var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
|
|
302
302
|
|
|
303
303
|
var _document = document,
|
|
304
304
|
implementation = _document.implementation,
|
|
@@ -342,6 +342,33 @@ function createDOMPurify() {
|
|
|
342
342
|
var ALLOWED_ATTR = null;
|
|
343
343
|
var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray$1(html$1), _toConsumableArray$1(svg$1), _toConsumableArray$1(mathMl$1), _toConsumableArray$1(xml)));
|
|
344
344
|
|
|
345
|
+
/*
|
|
346
|
+
* Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.
|
|
347
|
+
* @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
|
|
348
|
+
* @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)
|
|
349
|
+
* @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
|
|
350
|
+
*/
|
|
351
|
+
var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
|
|
352
|
+
tagNameCheck: {
|
|
353
|
+
writable: true,
|
|
354
|
+
configurable: false,
|
|
355
|
+
enumerable: true,
|
|
356
|
+
value: null
|
|
357
|
+
},
|
|
358
|
+
attributeNameCheck: {
|
|
359
|
+
writable: true,
|
|
360
|
+
configurable: false,
|
|
361
|
+
enumerable: true,
|
|
362
|
+
value: null
|
|
363
|
+
},
|
|
364
|
+
allowCustomizedBuiltInElements: {
|
|
365
|
+
writable: true,
|
|
366
|
+
configurable: false,
|
|
367
|
+
enumerable: true,
|
|
368
|
+
value: false
|
|
369
|
+
}
|
|
370
|
+
}));
|
|
371
|
+
|
|
345
372
|
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
|
|
346
373
|
var FORBID_TAGS = null;
|
|
347
374
|
|
|
@@ -382,17 +409,6 @@ function createDOMPurify() {
|
|
|
382
409
|
* string (or a TrustedHTML object if Trusted Types are supported) */
|
|
383
410
|
var RETURN_DOM_FRAGMENT = false;
|
|
384
411
|
|
|
385
|
-
/* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
|
|
386
|
-
* `Node` is imported into the current `Document`. If this flag is not enabled the
|
|
387
|
-
* `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
|
|
388
|
-
* DOMPurify.
|
|
389
|
-
*
|
|
390
|
-
* This defaults to `true` starting DOMPurify 2.2.0. Note that setting it to `false`
|
|
391
|
-
* might cause XSS from attacks hidden in closed shadowroots in case the browser
|
|
392
|
-
* supports Declarative Shadow: DOM https://web.dev/declarative-shadow-dom/
|
|
393
|
-
*/
|
|
394
|
-
var RETURN_DOM_IMPORT = true;
|
|
395
|
-
|
|
396
412
|
/* Try to return a Trusted Type object instead of a string, return a string in
|
|
397
413
|
* case Trusted Types are not supported */
|
|
398
414
|
var RETURN_TRUSTED_TYPE = false;
|
|
@@ -443,6 +459,10 @@ function createDOMPurify() {
|
|
|
443
459
|
|
|
444
460
|
var formElement = document.createElement('form');
|
|
445
461
|
|
|
462
|
+
var isRegexOrFunction = function isRegexOrFunction(testValue) {
|
|
463
|
+
return testValue instanceof RegExp || testValue instanceof Function;
|
|
464
|
+
};
|
|
465
|
+
|
|
446
466
|
/**
|
|
447
467
|
* _parseConfig
|
|
448
468
|
*
|
|
@@ -478,7 +498,6 @@ function createDOMPurify() {
|
|
|
478
498
|
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
|
|
479
499
|
RETURN_DOM = cfg.RETURN_DOM || false; // Default false
|
|
480
500
|
RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
|
|
481
|
-
RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT !== false; // Default true
|
|
482
501
|
RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
|
|
483
502
|
FORCE_BODY = cfg.FORCE_BODY || false; // Default false
|
|
484
503
|
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
|
@@ -486,7 +505,22 @@ function createDOMPurify() {
|
|
|
486
505
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
487
506
|
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
488
507
|
NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
|
|
489
|
-
|
|
508
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
|
|
509
|
+
CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
|
|
513
|
+
CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
|
|
517
|
+
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
PARSER_MEDIA_TYPE =
|
|
521
|
+
// eslint-disable-next-line unicorn/prefer-includes
|
|
522
|
+
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
|
|
523
|
+
|
|
490
524
|
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
491
525
|
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
|
|
492
526
|
return x;
|
|
@@ -807,7 +841,9 @@ function createDOMPurify() {
|
|
|
807
841
|
* @return {Iterator} iterator instance
|
|
808
842
|
*/
|
|
809
843
|
var _createIterator = function _createIterator(root) {
|
|
810
|
-
return createNodeIterator.call(root.ownerDocument || root, root,
|
|
844
|
+
return createNodeIterator.call(root.ownerDocument || root, root,
|
|
845
|
+
// eslint-disable-next-line no-bitwise
|
|
846
|
+
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
|
|
811
847
|
};
|
|
812
848
|
|
|
813
849
|
/**
|
|
@@ -817,15 +853,7 @@ function createDOMPurify() {
|
|
|
817
853
|
* @return {Boolean} true if clobbered, false if safe
|
|
818
854
|
*/
|
|
819
855
|
var _isClobbered = function _isClobbered(elm) {
|
|
820
|
-
|
|
821
|
-
return false;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
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') {
|
|
825
|
-
return true;
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
return false;
|
|
856
|
+
return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function');
|
|
829
857
|
};
|
|
830
858
|
|
|
831
859
|
/**
|
|
@@ -907,6 +935,12 @@ function createDOMPurify() {
|
|
|
907
935
|
|
|
908
936
|
/* Remove element if anything forbids its presence */
|
|
909
937
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
938
|
+
/* Check if we have a custom element to handle */
|
|
939
|
+
if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
|
|
940
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
|
|
941
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
|
|
942
|
+
}
|
|
943
|
+
|
|
910
944
|
/* Keep content except for bad-listed elements */
|
|
911
945
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
912
946
|
var parentNode = getParentNode(currentNode) || currentNode.parentNode;
|
|
@@ -974,8 +1008,16 @@ function createDOMPurify() {
|
|
|
974
1008
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
975
1009
|
We don't need to check the value; it's always URI safe. */
|
|
976
1010
|
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
977
|
-
|
|
978
|
-
|
|
1011
|
+
if (
|
|
1012
|
+
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
1013
|
+
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1014
|
+
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
|
|
1015
|
+
_basicCustomElementTest(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||
|
|
1016
|
+
// Alternative, second condition checks if it's an `is`-attribute, AND
|
|
1017
|
+
// the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1018
|
+
lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {
|
|
1019
|
+
return false;
|
|
1020
|
+
}
|
|
979
1021
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
980
1022
|
} else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) ; else if (!value) ; else {
|
|
981
1023
|
return false;
|
|
@@ -984,6 +1026,16 @@ function createDOMPurify() {
|
|
|
984
1026
|
return true;
|
|
985
1027
|
};
|
|
986
1028
|
|
|
1029
|
+
/**
|
|
1030
|
+
* _basicCustomElementCheck
|
|
1031
|
+
* checks if at least one dash is included in tagName, and it's not the first char
|
|
1032
|
+
* for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
|
|
1033
|
+
* @param {string} tagName name of the tag of the node to sanitize
|
|
1034
|
+
*/
|
|
1035
|
+
var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
|
|
1036
|
+
return tagName.indexOf('-') > 0;
|
|
1037
|
+
};
|
|
1038
|
+
|
|
987
1039
|
/**
|
|
988
1040
|
* _sanitizeAttributes
|
|
989
1041
|
*
|
|
@@ -1180,7 +1232,15 @@ function createDOMPurify() {
|
|
|
1180
1232
|
IN_PLACE = false;
|
|
1181
1233
|
}
|
|
1182
1234
|
|
|
1183
|
-
if (IN_PLACE)
|
|
1235
|
+
if (IN_PLACE) {
|
|
1236
|
+
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
1237
|
+
if (dirty.nodeName) {
|
|
1238
|
+
var tagName = transformCaseFunc(dirty.nodeName);
|
|
1239
|
+
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
1240
|
+
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
} else if (dirty instanceof Node) {
|
|
1184
1244
|
/* If dirty is a DOM element, append to an empty document to avoid
|
|
1185
1245
|
elements being stripped by the parser */
|
|
1186
1246
|
body = _initDocument('<!---->');
|
|
@@ -1207,7 +1267,7 @@ function createDOMPurify() {
|
|
|
1207
1267
|
|
|
1208
1268
|
/* Check we have a DOM node from the data */
|
|
1209
1269
|
if (!body) {
|
|
1210
|
-
return RETURN_DOM ? null : emptyHTML;
|
|
1270
|
+
return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
|
|
1211
1271
|
}
|
|
1212
1272
|
}
|
|
1213
1273
|
|
|
@@ -1262,7 +1322,7 @@ function createDOMPurify() {
|
|
|
1262
1322
|
returnNode = body;
|
|
1263
1323
|
}
|
|
1264
1324
|
|
|
1265
|
-
if (
|
|
1325
|
+
if (ALLOWED_ATTR.shadowroot) {
|
|
1266
1326
|
/*
|
|
1267
1327
|
AdoptNode() is not used because internal state is not reset
|
|
1268
1328
|
(e.g. the past names map of a HTMLFormElement), this is safe
|
|
@@ -1278,6 +1338,11 @@ function createDOMPurify() {
|
|
|
1278
1338
|
|
|
1279
1339
|
var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
|
1280
1340
|
|
|
1341
|
+
/* Serialize doctype if allowed */
|
|
1342
|
+
if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
|
|
1343
|
+
serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1281
1346
|
/* Sanitize final string template-safe */
|
|
1282
1347
|
if (SAFE_FOR_TEMPLATES) {
|
|
1283
1348
|
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
|