Skip to content

Commit c19aa70

Browse files
nelstromcure53
authored andcommitted
feat: add tagName parameter to attributeNameCheck
Allow attributeNameCheck function to receive the tag name as an optional second parameter, enabling more granular control over which attributes are allowed for specific custom elements.
1 parent 2acfc7c commit c19aa70

File tree

14 files changed

+60
-12
lines changed

14 files changed

+60
-12
lines changed

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ const clean = DOMPurify.sanitize(dirty, {ALLOW_DATA_ATTR: false});
230230
// The same goes for their attributes. By default, the built-in or configured allow.list is used.
231231
//
232232
// You can use a RegExp literal to specify what is allowed or a predicate, examples for both can be seen below.
233+
// When using a predicate function for attributeNameCheck, it can optionally receive the tagName as a second parameter
234+
// for more granular control over which attributes are allowed for specific elements.
233235
// The default values are very restrictive to prevent accidental XSS bypasses. Handle with great care!
234236

235237
const clean = DOMPurify.sanitize(
@@ -264,6 +266,26 @@ const clean = DOMPurify.sanitize(
264266
},
265267
}
266268
); // <foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>
269+
270+
// Example with attributeNameCheck receiving tagName as a second parameter
271+
const clean = DOMPurify.sanitize(
272+
'<element-one attribute-one="1" attribute-two="2"></element-one><element-two attribute-one="1" attribute-two="2"></element-two>',
273+
{
274+
CUSTOM_ELEMENT_HANDLING: {
275+
tagNameCheck: (tagName) => tagName.match(/^element-(one|two)$/),
276+
attributeNameCheck: (attr, tagName) => {
277+
if (tagName === 'element-one') {
278+
return ['attribute-one'].includes(attr);
279+
} else if (tagName === 'element-two') {
280+
return ['attribute-two'].includes(attr);
281+
} else {
282+
return false;
283+
}
284+
},
285+
allowCustomizedBuiltInElements: false,
286+
},
287+
}
288+
); // <element-one attribute-one="1"></element-one><element-two attribute-two="2"></element-two>
267289
```
268290
### Control behavior relating to URI values
269291
```js

dist/purify.cjs.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ interface Config {
7676
* Regular expression or function to match to allowed attributes.
7777
* Default is null (disallow any attributes not on the allow list).
7878
*/
79-
attributeNameCheck?: RegExp | ((attributeName: string) => boolean) | null | undefined;
79+
attributeNameCheck?: RegExp | ((attributeName: string, tagName?: string) => boolean) | null | undefined;
8080
/**
8181
* Allow custom elements derived from built-ins if they pass `tagNameCheck`. Default is false.
8282
*/

dist/purify.cjs.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/purify.cjs.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/purify.es.d.mts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ interface Config {
7676
* Regular expression or function to match to allowed attributes.
7777
* Default is null (disallow any attributes not on the allow list).
7878
*/
79-
attributeNameCheck?: RegExp | ((attributeName: string) => boolean) | null | undefined;
79+
attributeNameCheck?: RegExp | ((attributeName: string, tagName?: string) => boolean) | null | undefined;
8080
/**
8181
* Allow custom elements derived from built-ins if they pass `tagNameCheck`. Default is false.
8282
*/

dist/purify.es.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,7 @@ function createDOMPurify() {
996996
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
997997
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
998998
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
999-
_isBasicCustomElement(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)) ||
999+
_isBasicCustomElement(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, lcTag)) ||
10001000
// Alternative, second condition checks if it's an `is`-attribute, AND
10011001
// the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
10021002
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 {

dist/purify.es.mjs.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/purify.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/purify.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/purify.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)