diff --git a/package-lock.json b/package-lock.json index e273684c16..2dfe4ff3cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "buffer": "^6.0.3", "classnames": "2.5.1", "copy-webpack-plugin": "^11.0.0", + "dompurify": "^3.1.7", "husky": "7.0.4", "joi": "^17.11.0", "js-cookie": "3.0.5", @@ -8875,6 +8876,11 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", + "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==" + }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", diff --git a/package.json b/package.json index e0a33bf98b..cf466ed93b 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "buffer": "^6.0.3", "classnames": "2.5.1", "copy-webpack-plugin": "^11.0.0", + "dompurify": "^3.1.7", "husky": "7.0.4", "joi": "^17.11.0", "js-cookie": "3.0.5", diff --git a/src/course-home/outline-tab/widgets/CourseHandouts.jsx b/src/course-home/outline-tab/widgets/CourseHandouts.jsx index ac90adad8b..1a426b89a4 100644 --- a/src/course-home/outline-tab/widgets/CourseHandouts.jsx +++ b/src/course-home/outline-tab/widgets/CourseHandouts.jsx @@ -3,7 +3,7 @@ import { useSelector } from 'react-redux'; import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; -import LmsHtmlFragment from '../LmsHtmlFragment'; +import SanitizedHtmlFragment from '@src/generic/sanitized-html-fragment'; import messages from '../messages'; import { useModel } from '../../../generic/model-store'; @@ -22,10 +22,9 @@ const CourseHandouts = ({ intl }) => { return (

{intl.formatMessage(messages.handouts)}

-
); diff --git a/src/generic/sanitized-html-fragment/SanitizedHtmlFragment.jsx b/src/generic/sanitized-html-fragment/SanitizedHtmlFragment.jsx new file mode 100644 index 0000000000..a6ed13dc03 --- /dev/null +++ b/src/generic/sanitized-html-fragment/SanitizedHtmlFragment.jsx @@ -0,0 +1,25 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import dompurify from 'dompurify'; + +const SanitizedHtmlFragment = ({ + className, + html, +}) => { + const markup = { __html: dompurify.sanitize(html) }; + + return ( +
+ ); +}; + +SanitizedHtmlFragment.defaultProps = { + className: '', +}; + +SanitizedHtmlFragment.propTypes = { + className: PropTypes.string, + html: PropTypes.string.isRequired, +}; + +export default SanitizedHtmlFragment; diff --git a/src/generic/sanitized-html-fragment/index.js b/src/generic/sanitized-html-fragment/index.js new file mode 100644 index 0000000000..671bf2f180 --- /dev/null +++ b/src/generic/sanitized-html-fragment/index.js @@ -0,0 +1 @@ +export { default } from './SanitizedHtmlFragment';