使用sanitizeHtml与SvelteMarkdown时特殊字符转义及XSS防护问题求助
解决方案
核心思路:调整处理顺序,先解析Markdown再做HTML清洗
问题根源是两次转义:sanitizeHtml先把特殊字符转成HTML实体,SvelteMarkdown(基于marked)又会对实体中的&再次转义。反过来先解析Markdown生成HTML,再用sanitizeHtml清洗危险内容,既能避免重复转义,又能彻底防范XSS。
具体实现代码
<script> import SvelteMarkdown from 'svelte-markdown'; import { marked } from 'marked'; import sanitizeHtml from 'sanitize-html'; // 用户输入示例 let userInput = "Tom & Jerry\n\n<img src='x' onerror='alert(\"XSS\")'>"; // 1. 先把用户输入的Markdown转换为HTML const rawHtml = marked(userInput); // 2. 清洗HTML,过滤危险标签/属性 const safeHtml = sanitizeHtml(rawHtml, { // 按需配置允许的标签,比如保留Markdown常用的p、h1-h6、img等 allowedTags: [...sanitizeHtml.defaults.allowedTags, 'img'], // 限制标签允许的属性,比如img只保留src allowedAttributes: { img: ['src'] } }); </script> <!-- 直接渲染清洗后的安全HTML --> {@html safeHtml}
替代方案:配置sanitizeHtml解码实体后再解析Markdown
如果坚持先做清洗再解析Markdown,可以开启sanitizeHtml的decodeEntities选项,把已转义的实体还原为原始字符,避免marked二次转义:
<script> import SvelteMarkdown from 'svelte-markdown'; import sanitizeHtml from 'sanitize-html'; let userInput = "Tom & Jerry\n\n<img src='x' onerror='alert(\"XSS\")'>"; // 清洗时解码实体,同时过滤所有HTML标签(避免XSS) const cleanedInput = sanitizeHtml(userInput, { decodeEntities: true, allowedTags: [], allowedAttributes: {} }); </script> <!-- 用SvelteMarkdown解析清洗后的纯Markdown内容 --> <SvelteMarkdown source={cleanedInput} />
说明
- 方案一更灵活:支持Markdown生成的所有合法HTML标签,同时精准过滤危险属性(比如
onerror)。 - 方案二更简单:直接过滤所有HTML标签,只保留纯Markdown语法,适合不需要用户输入HTML的场景。
内容的提问来源于stack exchange,提问作者Milano
相关产品推荐
相关产品推荐

