Update DOMPurify to version 3.0.9

This commit is contained in:
Théophile Diot 2024-02-28 14:05:06 +01:00
parent 6d08031054
commit 30b23771b0
No known key found for this signature in database
GPG key ID: 248FEA4BAE400D06
3 changed files with 92 additions and 60 deletions

File diff suppressed because one or more lines are too long

View file

@ -19,6 +19,7 @@ import {
typeErrorCreate,
lookupGetter,
create,
objectHasOwnProperty,
} from './utils.js';
const getGlobal = function () {
@ -28,9 +29,9 @@ const getGlobal = function () {
/**
* Creates a no-op policy for internal use only.
* Don't export this function outside this module!
* @param {?TrustedTypePolicyFactory} trustedTypes The policy factory.
* @param {TrustedTypePolicyFactory} trustedTypes The policy factory.
* @param {HTMLScriptElement} purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).
* @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
* @return {TrustedTypePolicy} The policy created (or null, if Trusted Types
* are not supported or creating the policy failed).
*/
const _createTrustedTypesPolicy = function (trustedTypes, purifyHostElement) {
@ -412,8 +413,8 @@ function createDOMPurify(window = getGlobal()) {
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);
? DEFAULT_PARSER_MEDIA_TYPE
: cfg.PARSER_MEDIA_TYPE;
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
transformCaseFunc =
@ -422,47 +423,41 @@ function createDOMPurify(window = getGlobal()) {
: stringToLowerCase;
/* Set configuration parameters */
ALLOWED_TAGS =
'ALLOWED_TAGS' in cfg
? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc)
: DEFAULT_ALLOWED_TAGS;
ALLOWED_ATTR =
'ALLOWED_ATTR' in cfg
? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc)
: DEFAULT_ALLOWED_ATTR;
ALLOWED_NAMESPACES =
'ALLOWED_NAMESPACES' in cfg
? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString)
: DEFAULT_ALLOWED_NAMESPACES;
URI_SAFE_ATTRIBUTES =
'ADD_URI_SAFE_ATTR' in cfg
? addToSet(
clone(DEFAULT_URI_SAFE_ATTRIBUTES), // eslint-disable-line indent
cfg.ADD_URI_SAFE_ATTR, // eslint-disable-line indent
transformCaseFunc // eslint-disable-line indent
) // eslint-disable-line indent
: DEFAULT_URI_SAFE_ATTRIBUTES;
DATA_URI_TAGS =
'ADD_DATA_URI_TAGS' in cfg
? addToSet(
clone(DEFAULT_DATA_URI_TAGS), // eslint-disable-line indent
cfg.ADD_DATA_URI_TAGS, // eslint-disable-line indent
transformCaseFunc // eslint-disable-line indent
) // eslint-disable-line indent
: DEFAULT_DATA_URI_TAGS;
FORBID_CONTENTS =
'FORBID_CONTENTS' in cfg
? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc)
: DEFAULT_FORBID_CONTENTS;
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;
ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS')
? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc)
: DEFAULT_ALLOWED_TAGS;
ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR')
? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc)
: DEFAULT_ALLOWED_ATTR;
ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES')
? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString)
: DEFAULT_ALLOWED_NAMESPACES;
URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR')
? addToSet(
clone(DEFAULT_URI_SAFE_ATTRIBUTES), // eslint-disable-line indent
cfg.ADD_URI_SAFE_ATTR, // eslint-disable-line indent
transformCaseFunc // eslint-disable-line indent
) // eslint-disable-line indent
: DEFAULT_URI_SAFE_ATTRIBUTES;
DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS')
? addToSet(
clone(DEFAULT_DATA_URI_TAGS), // eslint-disable-line indent
cfg.ADD_DATA_URI_TAGS, // eslint-disable-line indent
transformCaseFunc // eslint-disable-line indent
) // eslint-disable-line indent
: DEFAULT_DATA_URI_TAGS;
FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS')
? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc)
: DEFAULT_FORBID_CONTENTS;
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS')
? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc)
: {};
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR')
? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc)
: {};
USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES')
? cfg.USE_PROFILES
: false;
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
@ -515,7 +510,7 @@ function createDOMPurify(window = getGlobal()) {
/* Parse profile info */
if (USE_PROFILES) {
ALLOWED_TAGS = addToSet({}, [...TAGS.text]);
ALLOWED_TAGS = addToSet({}, TAGS.text);
ALLOWED_ATTR = [];
if (USE_PROFILES.html === true) {
addToSet(ALLOWED_TAGS, TAGS.html);
@ -658,12 +653,15 @@ function createDOMPurify(window = getGlobal()) {
/* Keep track of all possible SVG and MathML tags
* so that we can perform the namespace checks
* correctly. */
const ALL_SVG_TAGS = addToSet({}, TAGS.svg);
addToSet(ALL_SVG_TAGS, TAGS.svgFilters);
addToSet(ALL_SVG_TAGS, TAGS.svgDisallowed);
const ALL_MATHML_TAGS = addToSet({}, TAGS.mathMl);
addToSet(ALL_MATHML_TAGS, TAGS.mathMlDisallowed);
const ALL_SVG_TAGS = addToSet({}, [
...TAGS.svg,
...TAGS.svgFilters,
...TAGS.svgDisallowed,
]);
const ALL_MATHML_TAGS = addToSet({}, [
...TAGS.mathMl,
...TAGS.mathMlDisallowed,
]);
/**
* @param {Element} element a DOM element whose namespace is being checked
@ -781,6 +779,7 @@ function createDOMPurify(window = getGlobal()) {
*/
const _forceRemove = function (node) {
arrayPush(DOMPurify.removed, { element: node });
try {
// eslint-disable-next-line unicorn/prefer-dom-node-remove
node.parentNode.removeChild(node);
@ -1190,7 +1189,7 @@ function createDOMPurify(window = getGlobal()) {
* @returns {boolean} Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
*/
const _isBasicCustomElement = function (tagName) {
return tagName.indexOf('-') > 0;
return tagName !== 'annotation-xml' && tagName.indexOf('-') > 0;
};
/**

View file

@ -46,6 +46,8 @@ const stringReplace = unapply(String.prototype.replace);
const stringIndexOf = unapply(String.prototype.indexOf);
const stringTrim = unapply(String.prototype.trim);
const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
const regExpTest = unapply(RegExp.prototype.test);
const typeErrorCreate = unconstruct(TypeError);
@ -107,18 +109,48 @@ function addToSet(set, array, transformCaseFunc = stringToLowerCase) {
return set;
}
/**
* Clean up an array to harden against CSPP
*
* @param {Array} array - The array to be cleaned.
* @returns {Array} The cleaned version of the array
*/
function cleanArray(array) {
for (let index = 0; index < array.length; index++) {
const isPropertyExist = objectHasOwnProperty(array, index);
if (!isPropertyExist) {
array[index] = null;
}
}
return array;
}
/**
* Shallow clone an object
*
* @param {Object} object - The object to be cloned.
* @returns {Object} A new object that copies the original.
*/
export function clone(object) {
function clone(object) {
const newObject = create(null);
for (const [property, value] of entries(object)) {
if (getOwnPropertyDescriptor(object, property) !== undefined) {
newObject[property] = value;
const isPropertyExist = objectHasOwnProperty(object, property);
if (isPropertyExist) {
if (Array.isArray(value)) {
newObject[property] = cleanArray(value);
} else if (
value &&
typeof value === 'object' &&
value.constructor === Object
) {
newObject[property] = clone(value);
} else {
newObject[property] = value;
}
}
}
@ -149,8 +181,7 @@ function lookupGetter(object, prop) {
object = getPrototypeOf(object);
}
function fallbackValue(element) {
console.warn('fallback value for', element);
function fallbackValue() {
return null;
}
@ -172,7 +203,9 @@ export {
isFrozen,
setPrototypeOf,
seal,
clone,
create,
objectHasOwnProperty,
// RegExp
regExpTest,
// String