fix: sanitizer svg to avoid xss (#16606)

This commit is contained in:
Joel
2025-03-24 14:36:07 +08:00
committed by GitHub
parent 9701b573e0
commit 16b6ffd915
4 changed files with 21 additions and 24 deletions

View File

@@ -27,6 +27,7 @@ import ThinkBlock from '@/app/components/base/markdown-blocks/think-block'
import { Theme } from '@/types/app'
import useTheme from '@/hooks/use-theme'
import cn from '@/utils/classnames'
import SVGRenderer from './svg-gallery'
// Available language https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/AVAILABLE_LANGUAGES_HLJS.MD
const capitalizationLanguageNameMap: Record<string, string> = {
@@ -136,14 +137,13 @@ const CodeBlock: any = memo(({ inline, className, children, ...props }: any) =>
</div>
)
}
// Attention: SVGRenderer has xss vulnerability
// else if (language === 'svg' && isSVG) {
// return (
// <ErrorBoundary>
// <SVGRenderer content={content} />
// </ErrorBoundary>
// )
// }
else if (language === 'svg' && isSVG) {
return (
<ErrorBoundary>
<SVGRenderer content={content} />
</ErrorBoundary>
)
}
else {
return (
<SyntaxHighlighter
@@ -240,19 +240,11 @@ const Link = ({ node, ...props }: any) => {
}
}
function escapeSVGTags(htmlString: string): string {
return htmlString.replace(/(<svg[\s\S]*?>)([\s\S]*?)(<\/svg>)/gi, (match: string, openTag: string, innerContent: string, closeTag: string): string => {
return openTag.replace(/</g, '&lt;').replace(/>/g, '&gt;')
+ innerContent.replace(/</g, '&lt;').replace(/>/g, '&gt;')
+ closeTag.replace(/</g, '&lt;').replace(/>/g, '&gt;')
})
}
export function Markdown(props: { content: string; className?: string; customDisallowedElements?: string[] }) {
const latexContent = flow([
preprocessThinkTag,
preprocessLaTeX,
])(escapeSVGTags(props.content))
])(props.content)
return (
<div className={cn('markdown-body', '!text-text-primary', props.className)}>

View File

@@ -1,6 +1,7 @@
import { useEffect, useRef, useState } from 'react'
import { SVG } from '@svgdotjs/svg.js'
import ImagePreview from '@/app/components/base/image-uploader/image-preview'
import DOMPurify from 'dompurify'
export const SVGRenderer = ({ content }: { content: string }) => {
const svgRef = useRef<HTMLDivElement>(null)
@@ -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))