Skip to content

Commit fe360ae

Browse files
Use DOMPurify to sanitize and mitigate XSS attacks (#3049)
* Use `DOMPurify` to sanitize and mitigate XSS attacks * Allow `target` attribute and update Markdown UI Test Snapshot
1 parent 42c78c0 commit fe360ae

File tree

4 files changed

+30
-5
lines changed

4 files changed

+30
-5
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"array-move": "^4.0.0",
4848
"browserfs": "^1.4.3",
4949
"classnames": "^2.3.2",
50+
"dompurify": "^3.1.6",
5051
"flexboxgrid": "^6.3.1",
5152
"flexboxgrid-helpers": "^1.1.3",
5253
"hastscript": "^9.0.0",
@@ -109,6 +110,7 @@
109110
"@testing-library/jest-dom": "^6.0.0",
110111
"@testing-library/react": "^14.0.0",
111112
"@testing-library/user-event": "^14.4.3",
113+
"@types/dompurify": "^3.0.5",
112114
"@types/estree": "^1.0.5",
113115
"@types/gapi": "^0.0.44",
114116
"@types/gapi.auth2": "^0.0.57",

src/commons/Markdown.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Classes } from '@blueprintjs/core';
22
import classNames from 'classnames';
3+
import DOMPurify from 'dompurify';
34
import React from 'react';
45
import { Converter } from 'showdown';
56

@@ -24,7 +25,12 @@ const Markdown: React.FC<Props> = props => {
2425
return (
2526
<div
2627
className={classNames(props.className ? props.className : 'md', Classes.RUNNING_TEXT)}
27-
dangerouslySetInnerHTML={{ __html: converter.makeHtml(props.content) }}
28+
dangerouslySetInnerHTML={{
29+
__html: DOMPurify.sanitize(converter.makeHtml(props.content), {
30+
USE_PROFILES: { html: true },
31+
ADD_ATTR: ['target']
32+
})
33+
}}
2834
/>
2935
);
3036
};

src/commons/__tests__/__snapshots__/Markdown.tsx.snap

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ exports[`Markdown page renders correctly 1`] = `
66
dangerouslySetInnerHTML={
77
Object {
88
"__html": "<p>Welcome to the Source Academy playground!</p>
9-
<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>
10-
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>
11-
<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>
12-
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>",
9+
<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>
10+
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>
11+
<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>
12+
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>",
1313
}
1414
}
1515
/>

yarn.lock

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2936,6 +2936,13 @@
29362936
dependencies:
29372937
"@types/ms" "*"
29382938

2939+
"@types/dompurify@^3.0.5":
2940+
version "3.0.5"
2941+
resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-3.0.5.tgz#02069a2fcb89a163bacf1a788f73cb415dd75cb7"
2942+
integrity sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==
2943+
dependencies:
2944+
"@types/trusted-types" "*"
2945+
29392946
"@types/eslint@^7.29.0 || ^8.4.1":
29402947
version "8.21.1"
29412948
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.21.1.tgz#110b441a210d53ab47795124dbc3e9bb993d1e7c"
@@ -3279,6 +3286,11 @@
32793286
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
32803287
integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==
32813288

3289+
"@types/trusted-types@*":
3290+
version "2.0.7"
3291+
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
3292+
integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==
3293+
32823294
"@types/trusted-types@^2.0.2":
32833295
version "2.0.3"
32843296
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.3.tgz#a136f83b0758698df454e328759dbd3d44555311"
@@ -5950,6 +5962,11 @@ domhandler@^5.0.2, domhandler@^5.0.3:
59505962
dependencies:
59515963
domelementtype "^2.3.0"
59525964

5965+
dompurify@^3.1.6:
5966+
version "3.1.6"
5967+
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.6.tgz#43c714a94c6a7b8801850f82e756685300a027e2"
5968+
integrity sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==
5969+
59535970
domutils@^1.7.0:
59545971
version "1.7.0"
59555972
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"

0 commit comments

Comments
 (0)