Skip to content

Commit

Permalink
Use DOMPurify to sanitize and mitigate XSS attacks (#3049)
Browse files Browse the repository at this point in the history
* Use `DOMPurify` to sanitize and mitigate XSS attacks

* Allow `target` attribute and update Markdown UI Test Snapshot
  • Loading branch information
TheMythologist authored Sep 24, 2024
1 parent 42c78c0 commit fe360ae
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 5 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"array-move": "^4.0.0",
"browserfs": "^1.4.3",
"classnames": "^2.3.2",
"dompurify": "^3.1.6",
"flexboxgrid": "^6.3.1",
"flexboxgrid-helpers": "^1.1.3",
"hastscript": "^9.0.0",
Expand Down Expand Up @@ -109,6 +110,7 @@
"@testing-library/jest-dom": "^6.0.0",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/dompurify": "^3.0.5",
"@types/estree": "^1.0.5",
"@types/gapi": "^0.0.44",
"@types/gapi.auth2": "^0.0.57",
Expand Down
8 changes: 7 additions & 1 deletion src/commons/Markdown.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Classes } from '@blueprintjs/core';
import classNames from 'classnames';
import DOMPurify from 'dompurify';
import React from 'react';
import { Converter } from 'showdown';

Expand All @@ -24,7 +25,12 @@ const Markdown: React.FC<Props> = props => {
return (
<div
className={classNames(props.className ? props.className : 'md', Classes.RUNNING_TEXT)}
dangerouslySetInnerHTML={{ __html: converter.makeHtml(props.content) }}
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(converter.makeHtml(props.content), {
USE_PROFILES: { html: true },
ADD_ATTR: ['target']
})
}}
/>
);
};
Expand Down
8 changes: 4 additions & 4 deletions src/commons/__tests__/__snapshots__/Markdown.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ exports[`Markdown page renders correctly 1`] = `
dangerouslySetInnerHTML={
Object {
"__html": "<p>Welcome to the Source Academy playground!</p>
<p>The book <a href=\\"https://sourceacademy.org/sicpjs/\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\"><em>Structure and Interpretation of Computer Programs, JavaScript Edition</em></a>
uses JavaScript sublanguages that we call <a href=\\"https://docs.sourceacademy.org/\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\"><em>Source</em></a>. You have chosen the sublanguage <a href=\\"https://docs.sourceacademy.org/source_1/\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\"><em>Source §1</em></a>.</p>
<p>In the editor on the left, you can use the <a href=\\"https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\"><em>Ace keyboard shortcuts</em></a>
and also the <a href=\\"https://github.com/source-academy/frontend/wiki/Source-Academy-Keyboard-Shortcuts\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\"><em>Source Academy keyboard shortcuts</em></a>.</p>",
<p>The book <a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"https://sourceacademy.org/sicpjs/\\"><em>Structure and Interpretation of Computer Programs, JavaScript Edition</em></a>
uses JavaScript sublanguages that we call <a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"https://docs.sourceacademy.org/\\"><em>Source</em></a>. You have chosen the sublanguage <a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"https://docs.sourceacademy.org/source_1/\\"><em>Source §1</em></a>.</p>
<p>In the editor on the left, you can use the <a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts\\"><em>Ace keyboard shortcuts</em></a>
and also the <a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"https://github.com/source-academy/frontend/wiki/Source-Academy-Keyboard-Shortcuts\\"><em>Source Academy keyboard shortcuts</em></a>.</p>",
}
}
/>
Expand Down
17 changes: 17 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2936,6 +2936,13 @@
dependencies:
"@types/ms" "*"

"@types/dompurify@^3.0.5":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-3.0.5.tgz#02069a2fcb89a163bacf1a788f73cb415dd75cb7"
integrity sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==
dependencies:
"@types/trusted-types" "*"

"@types/eslint@^7.29.0 || ^8.4.1":
version "8.21.1"
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.21.1.tgz#110b441a210d53ab47795124dbc3e9bb993d1e7c"
Expand Down Expand Up @@ -3279,6 +3286,11 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==

"@types/trusted-types@*":
version "2.0.7"
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==

"@types/trusted-types@^2.0.2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.3.tgz#a136f83b0758698df454e328759dbd3d44555311"
Expand Down Expand Up @@ -5950,6 +5962,11 @@ domhandler@^5.0.2, domhandler@^5.0.3:
dependencies:
domelementtype "^2.3.0"

dompurify@^3.1.6:
version "3.1.6"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.6.tgz#43c714a94c6a7b8801850f82e756685300a027e2"
integrity sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==

domutils@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
Expand Down

0 comments on commit fe360ae

Please sign in to comment.