From 21481dbd887b4b19cc8d6e288ed06ffcb53cb004 Mon Sep 17 00:00:00 2001 From: iven Date: Thu, 21 May 2026 22:34:58 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20ArticlePhonePreview=20XSS=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E2=80=94=20DOMPurify=20=E5=87=80=E5=8C=96?= =?UTF-8?q?=20dangerouslySetInnerHTML?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 安装 dompurify + @types/dompurify - ArticlePhonePreview 使用 DOMPurify.sanitize() 防止 HTML 注入 --- apps/web/package.json | 2 ++ apps/web/pnpm-lock.yaml | 27 +++++++++++++++++++ .../articleEditor/ArticlePhonePreview.tsx | 3 ++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/apps/web/package.json b/apps/web/package.json index 14cfdc5..51e17b4 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -24,6 +24,7 @@ "antd": "^6.3.5", "axios": "^1.15.0", "dayjs": "^1.11.20", + "dompurify": "^3.4.5", "react": "^19.2.4", "react-dom": "^19.2.4", "react-router-dom": "^7.14.0", @@ -36,6 +37,7 @@ "@tailwindcss/vite": "^4.2.2", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", + "@types/dompurify": "^3.2.0", "@types/node": "^24.12.2", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", diff --git a/apps/web/pnpm-lock.yaml b/apps/web/pnpm-lock.yaml index 0e7831b..b510873 100644 --- a/apps/web/pnpm-lock.yaml +++ b/apps/web/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: dayjs: specifier: ^1.11.20 version: 1.11.20 + dompurify: + specifier: ^3.4.5 + version: 3.4.5 react: specifier: ^19.2.4 version: 19.2.5 @@ -69,6 +72,9 @@ importers: '@testing-library/react': specifier: ^16.3.2 version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@types/dompurify': + specifier: ^3.2.0 + version: 3.2.0 '@types/node': specifier: ^24.12.2 version: 24.12.2 @@ -1172,6 +1178,10 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/dompurify@3.2.0': + resolution: {integrity: sha512-Fgg31wv9QbLDA0SpTOXO3MaxySc4DKGLi8sna4/Utjo4r3ZRPdCt4UQee8BWr+Q5z21yifghREPJGYaEOEIACg==} + deprecated: This is a stub types definition. dompurify provides its own type definitions, so you do not need this installed. + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -1201,6 +1211,9 @@ packages: '@types/statuses@2.0.6': resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@typescript-eslint/eslint-plugin@8.58.1': resolution: {integrity: sha512-eSkwoemjo76bdXl2MYqtxg51HNwUSkWfODUOQ3PaTLZGh9uIWWFZIjyjaJnex7wXDu+TRx+ATsnSxdN9YWfRTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1769,6 +1782,9 @@ packages: dom7@3.0.0: resolution: {integrity: sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==} + dompurify@3.4.5: + resolution: {integrity: sha512-OrwIBKsdNSVEeubdJ1HBv/wNENRM9ytAVCv7YXt//A3vPdVMNuACRqK9mXCGCBW2ln7BT/A4X0jXHo2Gu89miA==} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -4199,6 +4215,10 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/dompurify@3.2.0': + dependencies: + dompurify: 3.4.5 + '@types/estree@1.0.8': {} '@types/event-emitter@0.3.5': {} @@ -4225,6 +4245,9 @@ snapshots: '@types/statuses@2.0.6': {} + '@types/trusted-types@2.0.7': + optional: true + '@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.2))(eslint@9.39.4(jiti@2.6.1))(typescript@6.0.2)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -4906,6 +4929,10 @@ snapshots: dependencies: ssr-window: 3.0.0 + dompurify@3.4.5: + optionalDependencies: + '@types/trusted-types': 2.0.7 + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 diff --git a/apps/web/src/pages/health/articleEditor/ArticlePhonePreview.tsx b/apps/web/src/pages/health/articleEditor/ArticlePhonePreview.tsx index f8f2c67..79715ae 100644 --- a/apps/web/src/pages/health/articleEditor/ArticlePhonePreview.tsx +++ b/apps/web/src/pages/health/articleEditor/ArticlePhonePreview.tsx @@ -1,4 +1,5 @@ import { useMemo } from 'react'; +import DOMPurify from 'dompurify'; interface ArticlePhonePreviewProps { title: string; @@ -240,7 +241,7 @@ export default function ArticlePhonePreview({
{content && content !== '


' ? ( -
+
) : (
在左侧编辑器中输入内容