From 0be41724fc2c6ac66799034375488716746e01d7 Mon Sep 17 00:00:00 2001 From: dservian Date: Fri, 12 Jul 2024 16:49:41 +0200 Subject: [PATCH] Implement DOMPurify to sanitize HTML content before rendering --- web/package-lock.json | 25 +++++++++++++++++++ web/package.json | 2 ++ .../components/chunk-card/index.tsx | 5 +++- .../knowledge-setting/category-panel.tsx | 3 ++- web/src/pages/chat/markdown-content/index.tsx | 3 ++- 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index ccc02d2d646..1a1b4e022dd 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -17,6 +17,7 @@ "classnames": "^2.5.1", "dagre": "^0.8.5", "dayjs": "^1.11.10", + "dompurify": "^3.1.6", "elkjs": "^0.9.3", "eventsource-parser": "^1.1.2", "human-id": "^4.1.1", @@ -52,6 +53,7 @@ "@testing-library/jest-dom": "^6.4.5", "@testing-library/react": "^15.0.7", "@types/dagre": "^0.7.52", + "@types/dompurify": "^3.0.5", "@types/jest": "^29.5.12", "@types/lodash": "^4.14.202", "@types/react": "^18.0.33", @@ -4856,6 +4858,16 @@ "@types/ms": "*" } }, + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmmirror.com/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/trusted-types": "*" + } + }, "node_modules/@types/eslint": { "version": "8.56.1", "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.56.1.tgz", @@ -5206,6 +5218,13 @@ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "dev": true }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/unist": { "version": "3.0.2", "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.2.tgz", @@ -10715,6 +10734,12 @@ "integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww==", "deprecated": "dommatrix is no longer maintained. Please use @thednp/dommatrix." }, + "node_modules/dompurify": { + "version": "3.1.6", + "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.1.6.tgz", + "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==", + "license": "(MPL-2.0 OR Apache-2.0)" + }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz", diff --git a/web/package.json b/web/package.json index a1e31514323..c5dc182054a 100644 --- a/web/package.json +++ b/web/package.json @@ -28,6 +28,7 @@ "classnames": "^2.5.1", "dagre": "^0.8.5", "dayjs": "^1.11.10", + "dompurify": "^3.1.6", "elkjs": "^0.9.3", "eventsource-parser": "^1.1.2", "human-id": "^4.1.1", @@ -63,6 +64,7 @@ "@testing-library/jest-dom": "^6.4.5", "@testing-library/react": "^15.0.7", "@types/dagre": "^0.7.52", + "@types/dompurify": "^3.0.5", "@types/jest": "^29.5.12", "@types/lodash": "^4.14.202", "@types/react": "^18.0.33", diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx b/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx index 9a00b359ca0..7e1bd73e0f4 100644 --- a/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx @@ -2,6 +2,7 @@ import Image from '@/components/image'; import { IChunk } from '@/interfaces/database/knowledge'; import { Card, Checkbox, CheckboxProps, Flex, Popover, Switch } from 'antd'; import classNames from 'classnames'; +import DOMPurify from 'dompurify'; import { useState } from 'react'; import { ChunkTextMode } from '../../constant'; @@ -73,7 +74,9 @@ const ChunkCard = ({ className={styles.content} >
{

diff --git a/web/src/pages/chat/markdown-content/index.tsx b/web/src/pages/chat/markdown-content/index.tsx index 278fa9f4719..e677557349e 100644 --- a/web/src/pages/chat/markdown-content/index.tsx +++ b/web/src/pages/chat/markdown-content/index.tsx @@ -6,6 +6,7 @@ import { IChunk } from '@/interfaces/database/knowledge'; import { getExtension } from '@/utils/documentUtils'; import { InfoCircleOutlined } from '@ant-design/icons'; import { Button, Flex, Popover, Space } from 'antd'; +import DOMPurify from 'dompurify'; import { useCallback } from 'react'; import Markdown from 'react-markdown'; import reactStringReplace from 'react-string-replace'; @@ -94,7 +95,7 @@ const MarkdownContent = ({ <Space direction={'vertical'}> <div dangerouslySetInnerHTML={{ - __html: chunkItem?.content_with_weight, + __html: DOMPurify.sanitize(chunkItem?.content_with_weight), }} className={styles.chunkContentText} ></div>