minor: sanitize activity feed editor content (#16533)

This commit is contained in:
Sachin Chaurasiya 2024-06-05 13:13:59 +05:30 committed by GitHub
parent 8d312f0853
commit c75d55ba4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 92 additions and 6 deletions

View File

@ -87,6 +87,7 @@
"cronstrue": "^1.122.0", "cronstrue": "^1.122.0",
"crypto-random-string-with-promisify-polyfill": "^5.0.0", "crypto-random-string-with-promisify-polyfill": "^5.0.0",
"diff": "^5.0.0", "diff": "^5.0.0",
"dompurify": "^3.1.5",
"eventemitter3": "^5.0.1", "eventemitter3": "^5.0.1",
"fast-json-patch": "^3.1.1", "fast-json-patch": "^3.1.1",
"history": "4.5.1", "history": "4.5.1",
@ -166,6 +167,7 @@
"@types/codemirror": "^0.0.104", "@types/codemirror": "^0.0.104",
"@types/dagre": "^0.7.47", "@types/dagre": "^0.7.47",
"@types/diff": "^5.0.2", "@types/diff": "^5.0.2",
"@types/dompurify": "^3.0.5",
"@types/jest": "^26.0.23", "@types/jest": "^26.0.23",
"@types/lodash": "^4.14.167", "@types/lodash": "^4.14.167",
"@types/luxon": "^3.0.1", "@types/luxon": "^3.0.1",

View File

@ -44,6 +44,7 @@ import {
} from '../../../utils/FeedUtils'; } from '../../../utils/FeedUtils';
import { LinkBlot } from '../../../utils/QuillLink/QuillLink'; import { LinkBlot } from '../../../utils/QuillLink/QuillLink';
import { insertMention, insertRef } from '../../../utils/QuillUtils'; import { insertMention, insertRef } from '../../../utils/QuillUtils';
import { getSanitizeContent } from '../../../utils/sanitize.utils';
import { getEntityIcon } from '../../../utils/TableUtils'; import { getEntityIcon } from '../../../utils/TableUtils';
import { editorRef } from '../../common/RichTextEditor/RichTextEditor.interface'; import { editorRef } from '../../common/RichTextEditor/RichTextEditor.interface';
import './feed-editor.less'; import './feed-editor.less';
@ -72,7 +73,9 @@ export const FeedEditor = forwardRef<editorRef, FeedEditorProp>(
) => { ) => {
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
const editorRef = useRef<ReactQuill>(null); const editorRef = useRef<ReactQuill>(null);
const [value, setValue] = useState<string>(defaultValue ?? ''); const [value, setValue] = useState(() =>
getSanitizeContent(defaultValue ?? '')
);
const [isMentionListOpen, toggleMentionList] = useState(false); const [isMentionListOpen, toggleMentionList] = useState(false);
const [isFocused, toggleFocus] = useState(false); const [isFocused, toggleFocus] = useState(false);
@ -246,11 +249,14 @@ export const FeedEditor = forwardRef<editorRef, FeedEditorProp>(
/** /**
* Handle onChange logic and set updated value to state * Handle onChange logic and set updated value to state
* @param value - updated value * @param updatedValue - updated value
*/ */
const handleOnChange = (value: string) => { const handleOnChange = (updatedValue: string) => {
setValue(value); setValue(updatedValue);
onChangeHandler?.(value);
// sanitize the content before sending it to the parent component
const sanitizedContent = getSanitizeContent(updatedValue);
onChangeHandler?.(sanitizedContent);
}; };
/** /**
@ -260,7 +266,8 @@ export const FeedEditor = forwardRef<editorRef, FeedEditorProp>(
getEditorValue() { getEditorValue() {
setValue(''); setValue('');
return HTMLToMarkdown.turndown(value); // sanitize the content before sending it to the parent component
return HTMLToMarkdown.turndown(getSanitizeContent(value));
}, },
clearEditorValue() { clearEditorValue() {
setValue(''); setValue('');

View File

@ -0,0 +1,43 @@
/*
* Copyright 2024 Collate.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { getSanitizeContent } from './sanitize.utils';
describe('getSanitizeContent', () => {
it('should sanitize the input 1', () => {
const mockHtml = `<details/open/ontoggle=confirm('XSS')>`;
const result = getSanitizeContent(mockHtml);
expect(result).toBe(`<details open=""></details>`);
});
it('should sanitize the input 2', () => {
const mockHtml = `<img src=x onerror=alert(1)//>`;
const result = getSanitizeContent(mockHtml);
expect(result).toBe(`<img src="x">`);
});
it('should sanitize the input 3', () => {
const mockHtml = `<svg><g/onload=alert(2)//<p>`;
const result = getSanitizeContent(mockHtml);
expect(result).toBe(`<svg><g></g></svg>`);
});
it('should sanitize the input 4', () => {
const mockHtml = `<p>abc<iframe//src=jAva&Tab;script:alert(3)>def</p>`;
const result = getSanitizeContent(mockHtml);
expect(result).toBe(`<p>abc</p>`);
});
});

View File

@ -0,0 +1,17 @@
/*
* Copyright 2024 Collate.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import DOMPurify from 'dompurify';
export const getSanitizeContent = (html: string): string => {
return DOMPurify.sanitize(html);
};

View File

@ -4113,6 +4113,13 @@
resolved "https://registry.yarnpkg.com/@types/diff/-/diff-5.0.2.tgz#dd565e0086ccf8bc6522c6ebafd8a3125c91c12b" resolved "https://registry.yarnpkg.com/@types/diff/-/diff-5.0.2.tgz#dd565e0086ccf8bc6522c6ebafd8a3125c91c12b"
integrity sha512-uw8eYMIReOwstQ0QKF0sICefSy8cNO/v7gOTiIy9SbwuHyEecJUm7qlgueOO5S1udZ5I/irVydHVwMchgzbKTg== integrity sha512-uw8eYMIReOwstQ0QKF0sICefSy8cNO/v7gOTiIy9SbwuHyEecJUm7qlgueOO5S1udZ5I/irVydHVwMchgzbKTg==
"@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-scope@^3.7.3": "@types/eslint-scope@^3.7.3":
version "3.7.4" version "3.7.4"
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16"
@ -4541,6 +4548,11 @@
"@types/testing-library__dom" "*" "@types/testing-library__dom" "*"
pretty-format "^25.1.0" pretty-format "^25.1.0"
"@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": "@types/trusted-types@^2.0.2":
version "2.0.4" version "2.0.4"
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.4.tgz#2b38784cd16957d3782e8e2b31c03bc1d13b4d65" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.4.tgz#2b38784cd16957d3782e8e2b31c03bc1d13b4d65"
@ -7203,6 +7215,11 @@ dompurify@^2.3.3:
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.10.tgz#901f7390ffe16a91a5a556b94043314cd4850385" resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.10.tgz#901f7390ffe16a91a5a556b94043314cd4850385"
integrity sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g== integrity sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g==
dompurify@^3.1.5:
version "3.1.5"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.5.tgz#2c6a113fc728682a0f55684b1388c58ddb79dc38"
integrity sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA==
domutils@^2.5.2, domutils@^2.6.0: domutils@^2.5.2, domutils@^2.6.0:
version "2.7.0" version "2.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.7.0.tgz#8ebaf0c41ebafcf55b0b72ec31c56323712c5442" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.7.0.tgz#8ebaf0c41ebafcf55b0b72ec31c56323712c5442"