Skip to content

Commit

Permalink
Merge pull request #1203 from basecamp/dom-purify
Browse files Browse the repository at this point in the history
Sanitize HTML with DOMPurify
  • Loading branch information
djmb authored Dec 9, 2024
2 parents d34ebea + 272c7e2 commit 0316042
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 2 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,8 @@
"postrelease": "git push && git push --tags",
"dev": "web-dev-server --app-index index.html --root-dir dist --node-resolve --open",
"start": "yarn build-assets && concurrently --kill-others --names js,css,dev-server 'yarn watch' 'yarn build-css --watch' 'yarn dev'"
},
"dependencies": {
"dompurify": "^3.2.0"
}
}
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const terserConfig = terser({
const type = comment.type
if (type == "comment2") {
// multiline comment
return /Copyright/.test(text)
return /@license|Copyright/.test(text)
}
},
},
Expand Down
30 changes: 30 additions & 0 deletions src/test/system/pasting_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,36 @@ testGroup("Pasting", { template: "editor_empty" }, () => {
delete window.unsanitized
})

test("paste data-trix-attachment encoded mathml", async () => {
window.unsanitized = []
const pasteData = {
"text/plain": "x",
"text/html": `\
copy<div data-trix-attachment="{&quot;contentType&quot;:&quot;text/html5&quot;,&quot;content&quot;:&quot;&lt;math&gt;&lt;mtext&gt;&lt;table&gt;&lt;mglyph&gt;&lt;style&gt;&lt;img src=x onerror=alert()&gt;&lt;/style&gt;XSS POC&quot;}"></div>me
`,
}

await pasteContent(pasteData)
await delay(20)
assert.deepEqual(window.unsanitized, [])
delete window.unsanitized
})

test("paste data-trix-attachment encoded embed", async () => {
window.unsanitized = []
const pasteData = {
"text/plain": "x",
"text/html": `\
copy<div data-trix-attachment="{&quot;contentType&quot;:&quot;text/html5&quot;,&quot;content&quot;:&quot;&lt;embed src='javascript:alert(1)'&gt;XSS POC&quot;}"></div>me
`,
}

await pasteContent(pasteData)
await delay(20)
assert.deepEqual(window.unsanitized, [])
delete window.unsanitized
})

test("prefers plain text when html lacks formatting", async () => {
const pasteData = {
"text/html": "<meta charset='utf-8'>a\nb",
Expand Down
4 changes: 3 additions & 1 deletion src/trix/models/html_sanitizer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import BasicObject from "trix/core/basic_object"

import { nodeIsAttachmentElement, removeNode, tagName, walkTree } from "trix/core/helpers"
import DOMPurify from "dompurify"

const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height language class".split(" ")
const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:".split(" ")
Expand Down Expand Up @@ -29,7 +30,8 @@ export default class HTMLSanitizer extends BasicObject {

sanitize() {
this.sanitizeElements()
return this.normalizeListElementNesting()
this.normalizeListElementNesting()
return DOMPurify.sanitize(this.body, { ADD_ATTR: [ "language" ], RETURN_DOM: true } )
}

getHTML() {
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2829,6 +2829,11 @@ domhandler@^4.2.0, domhandler@^4.3.1:
dependencies:
domelementtype "^2.2.0"

dompurify@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.0.tgz#53c414317c51503183696fcdef6dd3f916c607ed"
integrity sha512-AMdOzK44oFWqHEi0wpOqix/fUNY707OmoeFDnbi3Q5I8uOpy21ufUA5cDJPr0bosxrflOVD/H2DMSvuGKJGfmQ==

domutils@^2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
Expand Down

0 comments on commit 0316042

Please sign in to comment.