diff --git a/libs/perun/services/src/lib/html-escape.service.ts b/libs/perun/services/src/lib/html-escape.service.ts index 0649ac9d6..6af836dec 100644 --- a/libs/perun/services/src/lib/html-escape.service.ts +++ b/libs/perun/services/src/lib/html-escape.service.ts @@ -40,160 +40,166 @@ interface HtmlEscapedMessage { }) export class HtmlEscapeService { escapeDangerousHtml(html: string): EscapeOutput { - const config = { - WHOLE_DOCUMENT: true, - ALLOWED_TAGS: [ - 'a', - 'article', - 'aside', - 'b', - 'blockquote', - 'br', - 'button', - 'caption', - 'center', - 'cite', - 'decorator', - 'del', - 'details', - 'div', - 'em', - 'footer', - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'header', - 'i', - 'img', - 'kbd', - 'label', - 'li', - 'ol', - 'p', - 'pre', - 'section', - 'select', - 'span', - 'strong', - 'sup', - 'table', - 'tbody', - 'td', - 'textarea', - 'tfoot', - 'th', - 'thead', - 'tr', - 'ul', - ], - ALLOWED_ATTR: [ - 'align', - 'class', - 'color', - 'disabled', - 'height', - 'hidden', - 'href', - 'id', - 'label', - 'size', - 'span', - 'src', - 'srcset', - 'style', - 'width', - ], - ALLOWED_STYLE_PROPS: [ - 'color', - 'background-color', - 'font-size', - 'font-family', - 'text-align', - 'margin', - 'padding', - 'border', - 'width', - 'height', - 'display', - 'position', - 'top', - 'bottom', - 'left', - 'right', - 'overflow', - 'float', - 'clear', - 'z-index', - ], - }; - - const removedTags: string[] = []; - const removedAttributes: AttributeOut[] = []; - const removedStyles: StyleRemoved[] = []; - // Sanitize CSS properties (DOMPurify does not support sanitizing of style properties) - addHook('uponSanitizeAttribute', (_currentNode, data) => { - if (data.attrName !== 'style') return; - - const props = data.attrValue - .split(';') - .map((el) => el.trim()) - .filter((el) => el.length > 0); - for (let i = 0; i < props.length; i++) { - const prop = props[i]; - let [name, value] = prop.split(':'); - if (name === undefined || value === undefined) continue; - name = name.trim(); - value = value.trim(); - - if (!config.ALLOWED_STYLE_PROPS.includes(name)) { - const tagName = _currentNode.localName; - - removed.push({ - style: name, - tag: tagName, - }); - props[i] = ''; - continue; - } - props[i] = `${name}:${value};`; - } - data.attrValue = props.filter((el) => el.length > 0).join(' '); - }); - - const sanitized = sanitize(html, config); - // Hacky way to get the sanitized HTML and removed elements - const d = document.createElement('html'); - d.innerHTML = sanitized; - html = d.getElementsByTagName('body')[0].innerHTML; - - for (const el of removed) { - if ('element' in el) { - const e = el as ElementRemoved; - removedTags.push(e.element.localName); - } else if ('attribute' in el) { - const e = el as AttributeRemoved; - removedAttributes.push({ - attribute: e.attribute.localName, - tag: e.from.localName, - }); - } else if ('style' in el) { - const e = el as StyleRemoved; - removedStyles.push({ - style: e.style, - tag: e.tag, - }); - } - } - return { escapedHtml: html, - removedTags: removedTags, - removedAttrs: removedAttributes, - removedStyleProps: removedStyles, + removedTags: [], + removedAttrs: [], + removedStyleProps: [], }; + // const config = { + // WHOLE_DOCUMENT: true, + // ALLOWED_TAGS: [ + // 'a', + // 'article', + // 'aside', + // 'b', + // 'blockquote', + // 'br', + // 'button', + // 'caption', + // 'center', + // 'cite', + // 'decorator', + // 'del', + // 'details', + // 'div', + // 'em', + // 'footer', + // 'h1', + // 'h2', + // 'h3', + // 'h4', + // 'h5', + // 'h6', + // 'header', + // 'i', + // 'img', + // 'kbd', + // 'label', + // 'li', + // 'ol', + // 'p', + // 'pre', + // 'section', + // 'select', + // 'span', + // 'strong', + // 'sup', + // 'table', + // 'tbody', + // 'td', + // 'textarea', + // 'tfoot', + // 'th', + // 'thead', + // 'tr', + // 'ul', + // ], + // ALLOWED_ATTR: [ + // 'align', + // 'class', + // 'color', + // 'disabled', + // 'height', + // 'hidden', + // 'href', + // 'id', + // 'label', + // 'size', + // 'span', + // 'src', + // 'srcset', + // 'style', + // 'width', + // ], + // ALLOWED_STYLE_PROPS: [ + // 'color', + // 'background-color', + // 'font-size', + // 'font-family', + // 'text-align', + // 'margin', + // 'padding', + // 'border', + // 'width', + // 'height', + // 'display', + // 'position', + // 'top', + // 'bottom', + // 'left', + // 'right', + // 'overflow', + // 'float', + // 'clear', + // 'z-index', + // ], + // }; + // + // const removedTags: string[] = []; + // const removedAttributes: AttributeOut[] = []; + // const removedStyles: StyleRemoved[] = []; + // // Sanitize CSS properties (DOMPurify does not support sanitizing of style properties) + // addHook('uponSanitizeAttribute', (_currentNode, data) => { + // if (data.attrName !== 'style') return; + // + // const props = data.attrValue + // .split(';') + // .map((el) => el.trim()) + // .filter((el) => el.length > 0); + // for (let i = 0; i < props.length; i++) { + // const prop = props[i]; + // let [name, value] = prop.split(':'); + // if (name === undefined || value === undefined) continue; + // name = name.trim(); + // value = value.trim(); + // + // if (!config.ALLOWED_STYLE_PROPS.includes(name)) { + // const tagName = _currentNode.localName; + // + // removed.push({ + // style: name, + // tag: tagName, + // }); + // props[i] = ''; + // continue; + // } + // props[i] = `${name}:${value};`; + // } + // data.attrValue = props.filter((el) => el.length > 0).join(' '); + // }); + // + // const sanitized = sanitize(html, config); + // // Hacky way to get the sanitized HTML and removed elements + // const d = document.createElement('html'); + // d.innerHTML = sanitized; + // html = d.getElementsByTagName('body')[0].innerHTML; + // + // for (const el of removed) { + // if ('element' in el) { + // const e = el as ElementRemoved; + // removedTags.push(e.element.localName); + // } else if ('attribute' in el) { + // const e = el as AttributeRemoved; + // removedAttributes.push({ + // attribute: e.attribute.localName, + // tag: e.from.localName, + // }); + // } else if ('style' in el) { + // const e = el as StyleRemoved; + // removedStyles.push({ + // style: e.style, + // tag: e.tag, + // }); + // } + // } + // + // return { + // escapedHtml: html, + // removedTags: removedTags, + // removedAttrs: removedAttributes, + // removedStyleProps: removedStyles, + // }; } generateErrorTooltip(errors: EscapeOutput): string {