diff --git a/src/purify.js b/src/purify.js
index 9be3e45e..f8ecacc7 100644
--- a/src/purify.js
+++ b/src/purify.js
@@ -380,29 +380,55 @@ function createDOMPurify(window = getGlobal()) {
/* Shield configuration object from prototype pollution */
cfg = clone(cfg);
+ PARSER_MEDIA_TYPE =
+ // eslint-disable-next-line unicorn/prefer-includes
+ SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1
+ ? (PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE)
+ : (PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE);
+
+ // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
+ transformCaseFunc =
+ PARSER_MEDIA_TYPE === 'application/xhtml+xml'
+ ? (x) => x
+ : stringToLowerCase;
+
/* Set configuration parameters */
ALLOWED_TAGS =
'ALLOWED_TAGS' in cfg
- ? addToSet({}, cfg.ALLOWED_TAGS)
+ ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc)
: DEFAULT_ALLOWED_TAGS;
ALLOWED_ATTR =
'ALLOWED_ATTR' in cfg
- ? addToSet({}, cfg.ALLOWED_ATTR)
+ ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc)
: DEFAULT_ALLOWED_ATTR;
URI_SAFE_ATTRIBUTES =
'ADD_URI_SAFE_ATTR' in cfg
- ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR)
+ ? addToSet(
+ clone(DEFAULT_URI_SAFE_ATTRIBUTES),
+ cfg.ADD_URI_SAFE_ATTR,
+ transformCaseFunc
+ )
: DEFAULT_URI_SAFE_ATTRIBUTES;
DATA_URI_TAGS =
'ADD_DATA_URI_TAGS' in cfg
- ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS)
+ ? addToSet(
+ clone(DEFAULT_DATA_URI_TAGS),
+ cfg.ADD_DATA_URI_TAGS,
+ transformCaseFunc
+ )
: DEFAULT_DATA_URI_TAGS;
FORBID_CONTENTS =
'FORBID_CONTENTS' in cfg
- ? addToSet({}, cfg.FORBID_CONTENTS)
+ ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc)
: DEFAULT_FORBID_CONTENTS;
- FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
- FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
+ FORBID_TAGS =
+ 'FORBID_TAGS' in cfg
+ ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc)
+ : {};
+ FORBID_ATTR =
+ 'FORBID_ATTR' in cfg
+ ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc)
+ : {};
USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
@@ -443,18 +469,6 @@ function createDOMPurify(window = getGlobal()) {
cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
}
- PARSER_MEDIA_TYPE =
- // eslint-disable-next-line unicorn/prefer-includes
- SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1
- ? (PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE)
- : (PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE);
-
- // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
- transformCaseFunc =
- PARSER_MEDIA_TYPE === 'application/xhtml+xml'
- ? (x) => x
- : stringToLowerCase;
-
if (SAFE_FOR_TEMPLATES) {
ALLOW_DATA_ATTR = false;
}
@@ -497,7 +511,7 @@ function createDOMPurify(window = getGlobal()) {
ALLOWED_TAGS = clone(ALLOWED_TAGS);
}
- addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
+ addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
}
if (cfg.ADD_ATTR) {
@@ -505,11 +519,11 @@ function createDOMPurify(window = getGlobal()) {
ALLOWED_ATTR = clone(ALLOWED_ATTR);
}
- addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
+ addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
}
if (cfg.ADD_URI_SAFE_ATTR) {
- addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
+ addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
}
if (cfg.FORBID_CONTENTS) {
@@ -517,7 +531,7 @@ function createDOMPurify(window = getGlobal()) {
FORBID_CONTENTS = clone(FORBID_CONTENTS);
}
- addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
+ addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
}
/* Add #text in case KEEP_CONTENT is set to true */
diff --git a/src/utils.js b/src/utils.js
index 285ea4f1..1ce7e9a7 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -58,7 +58,8 @@ export function unconstruct(func) {
}
/* Add properties to a lookup table */
-export function addToSet(set, array) {
+export function addToSet(set, array, transformCaseFunc) {
+ transformCaseFunc = transformCaseFunc ? transformCaseFunc : stringToLowerCase;
if (setPrototypeOf) {
// Make 'in' and truthy checks like Boolean(set.constructor)
// independent of any properties defined on Object.prototype.
@@ -70,7 +71,7 @@ export function addToSet(set, array) {
while (l--) {
let element = array[l];
if (typeof element === 'string') {
- const lcElement = stringToLowerCase(element);
+ const lcElement = transformCaseFunc(element);
if (lcElement !== element) {
// Config presets (e.g. tags.js, attrs.js) are immutable.
if (!isFrozen(array)) {
diff --git a/test/test-suite.js b/test/test-suite.js
index 7e5e286b..540764c5 100644
--- a/test/test-suite.js
+++ b/test/test-suite.js
@@ -1842,6 +1842,26 @@
});
});
+ QUnit.test(
+ 'Config-Flag tests: PARSER_MEDIA_TYPE + ALLOWED_TAGS/ALLOWED_ATTR',
+ function (assert) {
+ assert.contains(
+ DOMPurify.sanitize(
+ 'abc',
+ {
+ PARSER_MEDIA_TYPE: 'application/xhtml+xml',
+ ALLOWED_TAGS: ['a', 'CustomTag'],
+ ALLOWED_ATTR: ['href', 'CustomAttr'],
+ }
+ ),
+ [
+ 'abc' +
+ '',
+ ]
+ );
+ }
+ );
+
QUnit.test('Test invalid xml', function (assert) {
var tests = [
{