Skip to content

Commit

Permalink
chore: Experimentally removing the depth counter logic as we have bet…
Browse files Browse the repository at this point in the history
…ter defenses now
  • Loading branch information
cure53 committed May 27, 2024
1 parent bfeb9a9 commit 7cf4890
Show file tree
Hide file tree
Showing 10 changed files with 13 additions and 260 deletions.
61 changes: 2 additions & 59 deletions dist/purify.cjs.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/purify.cjs.js.map

Large diffs are not rendered by default.

61 changes: 2 additions & 59 deletions dist/purify.es.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ const stringTrim = unapply(String.prototype.trim);
const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
const regExpTest = unapply(RegExp.prototype.test);
const typeErrorCreate = unconstruct(TypeError);
function numberIsNaN(x) {
// eslint-disable-next-line unicorn/prefer-number-properties
return typeof x === 'number' && isNaN(x);
}

/**
* Creates a new function that calls the given function with a specified thisArg and arguments.
Expand Down Expand Up @@ -537,9 +533,6 @@ function createDOMPurify() {
/* Keep a reference to config to pass to hooks */
let CONFIG = null;

/* Specify the maximum element nesting depth to prevent mXSS */
const MAX_NESTING_DEPTH = 255;

/* Ideally, do not touch anything below this line */
/* ______________________________________________ */

Expand Down Expand Up @@ -950,11 +943,7 @@ function createDOMPurify() {
* @return {Boolean} true if clobbered, false if safe
*/
const _isClobbered = function _isClobbered(elm) {
return elm instanceof HTMLFormElement && (
// eslint-disable-next-line unicorn/no-typeof-undefined
typeof elm.__depth !== 'undefined' && typeof elm.__depth !== 'number' ||
// eslint-disable-next-line unicorn/no-typeof-undefined
typeof elm.__removalCount !== 'undefined' && typeof elm.__removalCount !== 'number' || 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' || typeof elm.hasChildNodes !== 'function');
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' || typeof elm.hasChildNodes !== 'function');
};

/**
Expand Down Expand Up @@ -1105,7 +1094,7 @@ function createDOMPurify() {
// eslint-disable-next-line complexity
const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
/* Make sure attribute cannot clobber */
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement || value === '__depth' || value === '__removalCount')) {
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
return false;
}

Expand Down Expand Up @@ -1296,32 +1285,9 @@ function createDOMPurify() {
if (_sanitizeElements(shadowNode)) {
continue;
}
const parentNode = getParentNode(shadowNode);

/* Set the nesting depth of an element */
if (shadowNode.nodeType === NODE_TYPE.element) {
if (parentNode && parentNode.__depth) {
/*
We want the depth of the node in the original tree, which can
change when it's removed from its parent.
*/
shadowNode.__depth = (shadowNode.__removalCount || 0) + parentNode.__depth + 1;
} else {
shadowNode.__depth = 1;
}
}

/*
* Remove an element if nested too deeply to avoid mXSS
* or if the __depth might have been tampered with
*/
if (shadowNode.__depth >= MAX_NESTING_DEPTH || shadowNode.__depth < 0 || numberIsNaN(shadowNode.__depth)) {
_forceRemove(shadowNode);
}

/* Deep shadow DOM detected */
if (shadowNode.content instanceof DocumentFragment) {
shadowNode.content.__depth = shadowNode.__depth;
_sanitizeShadowDOM(shadowNode.content);
}

Expand Down Expand Up @@ -1437,32 +1403,9 @@ function createDOMPurify() {
if (_sanitizeElements(currentNode)) {
continue;
}
const parentNode = getParentNode(currentNode);

/* Set the nesting depth of an element */
if (currentNode.nodeType === NODE_TYPE.element) {
if (parentNode && parentNode.__depth) {
/*
We want the depth of the node in the original tree, which can
change when it's removed from its parent.
*/
currentNode.__depth = (currentNode.__removalCount || 0) + parentNode.__depth + 1;
} else {
currentNode.__depth = 1;
}
}

/*
* Remove an element if nested too deeply to avoid mXSS
* or if the __depth might have been tampered with
*/
if (currentNode.__depth >= MAX_NESTING_DEPTH || currentNode.__depth < 0 || numberIsNaN(currentNode.__depth)) {
_forceRemove(currentNode);
}

/* Shadow DOM detected, sanitize it */
if (currentNode.content instanceof DocumentFragment) {
currentNode.content.__depth = currentNode.__depth;
_sanitizeShadowDOM(currentNode.content);
}

Expand Down
2 changes: 1 addition & 1 deletion dist/purify.es.mjs.map

Large diffs are not rendered by default.

61 changes: 2 additions & 59 deletions dist/purify.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/purify.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/purify.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/purify.min.js.map

Large diffs are not rendered by default.

Loading

0 comments on commit 7cf4890

Please sign in to comment.