From 3e4e301e9e152817be15bcd9a047a631263e2f08 Mon Sep 17 00:00:00 2001 From: BD <51322242+dalferth@users.noreply.github.com> Date: Thu, 26 Oct 2023 16:26:02 +0200 Subject: [PATCH 1/2] allow custom attributes and only allow specific elements --- .../html_sanitizer_allowed_attributes.js | 10 ++++++++ .../config/html_sanitizer_allowed_elements.js | 3 +++ .../html_sanitizer_allowed_protocols.js | 3 +++ .../html_sanitizer_forbidden_elements.js | 7 ++++++ .../html_sanitizer_forbidden_protocols.js | 5 ++++ src/trix/config/index.js | 5 ++++ src/trix/models/html_sanitizer.js | 25 +++++++++++-------- src/trix/views/piece_view.js | 14 ++++++++--- 8 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 src/trix/config/html_sanitizer_allowed_attributes.js create mode 100644 src/trix/config/html_sanitizer_allowed_elements.js create mode 100644 src/trix/config/html_sanitizer_allowed_protocols.js create mode 100644 src/trix/config/html_sanitizer_forbidden_elements.js create mode 100644 src/trix/config/html_sanitizer_forbidden_protocols.js diff --git a/src/trix/config/html_sanitizer_allowed_attributes.js b/src/trix/config/html_sanitizer_allowed_attributes.js new file mode 100644 index 000000000..7b96b3509 --- /dev/null +++ b/src/trix/config/html_sanitizer_allowed_attributes.js @@ -0,0 +1,10 @@ +const attributes = [ + "style", + "href", + "src", + "width", + "height", + "class" +] + +export default attributes diff --git a/src/trix/config/html_sanitizer_allowed_elements.js b/src/trix/config/html_sanitizer_allowed_elements.js new file mode 100644 index 000000000..68580c96c --- /dev/null +++ b/src/trix/config/html_sanitizer_allowed_elements.js @@ -0,0 +1,3 @@ +const allowedElements = [] + +export default allowedElements diff --git a/src/trix/config/html_sanitizer_allowed_protocols.js b/src/trix/config/html_sanitizer_allowed_protocols.js new file mode 100644 index 000000000..286823a0f --- /dev/null +++ b/src/trix/config/html_sanitizer_allowed_protocols.js @@ -0,0 +1,3 @@ +const allowedProtocols = [] + +export default allowedProtocols diff --git a/src/trix/config/html_sanitizer_forbidden_elements.js b/src/trix/config/html_sanitizer_forbidden_elements.js new file mode 100644 index 000000000..b1c5e4eef --- /dev/null +++ b/src/trix/config/html_sanitizer_forbidden_elements.js @@ -0,0 +1,7 @@ +const forbiddenElements = [ + "script", + "iframe", + "form" +] + +export default forbiddenElements diff --git a/src/trix/config/html_sanitizer_forbidden_protocols.js b/src/trix/config/html_sanitizer_forbidden_protocols.js new file mode 100644 index 000000000..a5bc2a18d --- /dev/null +++ b/src/trix/config/html_sanitizer_forbidden_protocols.js @@ -0,0 +1,5 @@ +const forbiddenProtocols = [ + "javascript:" +] + +export default forbiddenProtocols diff --git a/src/trix/config/index.js b/src/trix/config/index.js index 27f7abc2f..202cc5cf9 100644 --- a/src/trix/config/index.js +++ b/src/trix/config/index.js @@ -10,3 +10,8 @@ export { default as parser } from "./parser" export { default as textAttributes } from "./text_attributes" export { default as toolbar } from "./toolbar" export { default as undo } from "./undo" +export { default as htmlSanitizerAllowedAttributes } from "./html_sanitizer_allowed_attributes" +export { default as htmlSanitizerAllowedElements } from "./html_sanitizer_allowed_elements" +export { default as htmlSanitizerAllowedProtocols } from "./html_sanitizer_allowed_protocols" +export { default as htmlSanitizerForbiddenElements } from "./html_sanitizer_forbidden_elements" +export { default as htmlSanitizerForbiddenProtocols } from "./html_sanitizer_forbidden_protocols" diff --git a/src/trix/models/html_sanitizer.js b/src/trix/models/html_sanitizer.js index 6e342e51a..92616075d 100644 --- a/src/trix/models/html_sanitizer.js +++ b/src/trix/models/html_sanitizer.js @@ -1,10 +1,13 @@ import BasicObject from "trix/core/basic_object" import { nodeIsAttachmentElement, removeNode, tagName, walkTree } from "trix/core/helpers" - -const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height class".split(" ") -const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:".split(" ") -const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form".split(" ") +import { + htmlSanitizerAllowedAttributes, + htmlSanitizerAllowedElements, + htmlSanitizerAllowedProtocols, + htmlSanitizerForbiddenElements, + htmlSanitizerForbiddenProtocols +} from "../config" export default class HTMLSanitizer extends BasicObject { static sanitize(html, options) { @@ -13,11 +16,13 @@ export default class HTMLSanitizer extends BasicObject { return sanitizer } - constructor(html, { allowedAttributes, forbiddenProtocols, forbiddenElements } = {}) { + constructor(html, { allowedAttributes, allowedElements, allowedProtocols, forbiddenProtocols, forbiddenElements } = {}) { super(...arguments) - this.allowedAttributes = allowedAttributes || DEFAULT_ALLOWED_ATTRIBUTES - this.forbiddenProtocols = forbiddenProtocols || DEFAULT_FORBIDDEN_PROTOCOLS - this.forbiddenElements = forbiddenElements || DEFAULT_FORBIDDEN_ELEMENTS + this.allowedAttributes = allowedAttributes || htmlSanitizerAllowedAttributes + this.allowedElements = allowedElements || htmlSanitizerAllowedElements + this.allowedProtocols = allowedProtocols || htmlSanitizerAllowedProtocols + this.forbiddenElements = forbiddenElements || htmlSanitizerForbiddenElements + this.forbiddenProtocols = forbiddenProtocols || htmlSanitizerForbiddenProtocols this.body = createBodyElementForHTML(html) } @@ -63,7 +68,7 @@ export default class HTMLSanitizer extends BasicObject { sanitizeElement(element) { if (element.hasAttribute("href")) { - if (this.forbiddenProtocols.includes(element.protocol)) { + if (this.forbiddenProtocols.includes(element.protocol) || this.allowedProtocols.length > 0 && !this.allowedProtocols.includes(element.protocol)) { element.removeAttribute("href") } } @@ -96,7 +101,7 @@ export default class HTMLSanitizer extends BasicObject { } elementIsForbidden(element) { - return this.forbiddenElements.includes(tagName(element)) + return this.forbiddenElements.includes(tagName(element)) || this.allowedElements.length > 0 && !this.allowedElements.includes(tagName(element)) } elementIsntSerializable(element) { diff --git a/src/trix/views/piece_view.js b/src/trix/views/piece_view.js index c03d6c266..306478183 100644 --- a/src/trix/views/piece_view.js +++ b/src/trix/views/piece_view.js @@ -111,17 +111,25 @@ export default class PieceView extends ObjectView { } createContainerElement() { + const attributes = {} + let groupTagName + for (const key in this.attributes) { const value = this.attributes[key] const config = getTextConfig(key) if (config) { - if (config.groupTagName) { - const attributes = {} + if (!groupTagName && config.groupTagName) { + attributes[key] = value + groupTagName = config.groupTagName + } else if (config.groupTagName && groupTagName === config.groupTagName) { attributes[key] = value - return makeElement(config.groupTagName, attributes) } } } + + if (Object.entries(attributes).length > 0 && groupTagName) { + return makeElement(groupTagName, attributes) + } } preserveSpaces(string) { From 2c45ad84f9c382d8c71aa2df2591f276e7624474 Mon Sep 17 00:00:00 2001 From: BD <51322242+dalferth@users.noreply.github.com> Date: Thu, 26 Oct 2023 16:43:49 +0200 Subject: [PATCH 2/2] code style --- src/trix/config/html_sanitizer_allowed_attributes.js | 2 +- src/trix/config/html_sanitizer_forbidden_elements.js | 2 +- src/trix/config/html_sanitizer_forbidden_protocols.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/trix/config/html_sanitizer_allowed_attributes.js b/src/trix/config/html_sanitizer_allowed_attributes.js index 7b96b3509..27bc6f871 100644 --- a/src/trix/config/html_sanitizer_allowed_attributes.js +++ b/src/trix/config/html_sanitizer_allowed_attributes.js @@ -4,7 +4,7 @@ const attributes = [ "src", "width", "height", - "class" + "class", ] export default attributes diff --git a/src/trix/config/html_sanitizer_forbidden_elements.js b/src/trix/config/html_sanitizer_forbidden_elements.js index b1c5e4eef..7641ab742 100644 --- a/src/trix/config/html_sanitizer_forbidden_elements.js +++ b/src/trix/config/html_sanitizer_forbidden_elements.js @@ -1,7 +1,7 @@ const forbiddenElements = [ "script", "iframe", - "form" + "form", ] export default forbiddenElements diff --git a/src/trix/config/html_sanitizer_forbidden_protocols.js b/src/trix/config/html_sanitizer_forbidden_protocols.js index a5bc2a18d..8b8f7b28d 100644 --- a/src/trix/config/html_sanitizer_forbidden_protocols.js +++ b/src/trix/config/html_sanitizer_forbidden_protocols.js @@ -1,5 +1,5 @@ const forbiddenProtocols = [ - "javascript:" + "javascript:", ] export default forbiddenProtocols