From 061a765b7d64de9e826bde6c27bfcc060b24bc09 Mon Sep 17 00:00:00 2001 From: Joel Date: Mon, 24 Mar 2025 14:48:40 +0800 Subject: [PATCH] fix: sanitizer svg to avoid xss (#16608) --- web/app/components/base/markdown.tsx | 25 +++++++------------ web/app/components/base/svg-gallery/index.tsx | 3 ++- web/package.json | 1 + 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/web/app/components/base/markdown.tsx b/web/app/components/base/markdown.tsx index 94ffb9ff3e..425c9d4c11 100644 --- a/web/app/components/base/markdown.tsx +++ b/web/app/components/base/markdown.tsx @@ -10,6 +10,7 @@ import SyntaxHighlighter from 'react-syntax-highlighter' import { atelierHeathLight } from 'react-syntax-highlighter/dist/esm/styles/hljs' import { Component, memo, useMemo, useRef, useState } from 'react' import type { CodeComponent } from 'react-markdown/lib/ast-to-react' +import SVGRenderer from './svg-gallery' import cn from '@/utils/classnames' import CopyBtn from '@/app/components/base/copy-btn' import SVGBtn from '@/app/components/base/svg' @@ -118,13 +119,13 @@ const CodeBlock: CodeComponent = memo(({ inline, className, children, ...props } ) } - // else if (language === 'svg' && isSVG) { - // return ( - // - // - // - // ) - // } + else if (language === 'svg' && isSVG) { + return ( + + + + ) + } else { return ( { } } -function escapeSVGTags(htmlString: string): string { - return htmlString.replace(/()([\s\S]*?)(<\/svg>)/gi, (match: string, openTag: string, innerContent: string, closeTag: string): string => { - return openTag.replace(//g, '>') - + innerContent.replace(//g, '>') - + closeTag.replace(//g, '>') - }) -} - export function Markdown(props: { content: string; className?: string }) { - const latexContent = preprocessLaTeX(escapeSVGTags(props.content)) + const latexContent = preprocessLaTeX(props.content) return (
{ @@ -44,7 +45,7 @@ export const SVGRenderer = ({ content }: { content: string }) => { svgRef.current.style.width = `${Math.min(originalWidth, 298)}px` - const rootElement = draw.svg(content) + const rootElement = draw.svg(DOMPurify.sanitize(content)) rootElement.click(() => { setImagePreview(svgToDataURL(svgElement as Element)) diff --git a/web/package.json b/web/package.json index 25615a8592..2e10d9c5ad 100644 --- a/web/package.json +++ b/web/package.json @@ -51,6 +51,7 @@ "crypto-js": "^4.2.0", "dayjs": "^1.11.7", "decimal.js": "^10.4.3", + "dompurify": "^3.2.4", "echarts": "^5.5.1", "echarts-for-react": "^3.0.2", "elkjs": "^0.9.3",