直接用 innerhtml 插入 svg 是 xss 入口,因其被浏览器视为可执行 xml+html 混合体;必须禁用字符串拼接插入,优先使用 标签或 dompurify(启用 svg profile)净化,服务端需 xml 解析器结构级清洗,静态展示应转 png。

直接用 innerHTML 插入 SVG 就是 XSS 入口
浏览器把内联 <svg></svg> 当作可执行 XML+HTML 混合体,不是“图片”而是“脚本容器”。onload、<script></script>、<foreignobject></foreignobject>、CDATA 绕过等都会立刻触发。哪怕只插入一行 <svg onload="alert(1)"></svg>,只要走 innerHTML 或 document.write(),就等于主动执行攻击者代码。
常见错误现象:
– 用户上传 SVG 图标后,页面渲染时弹窗或发请求
– 后端返回 SVG 字符串,前端用 el.innerHTML = svgStr 直接挂载
– 用正则替换 <script></script> 标签但漏掉 <svg><g onclick="..."></g></svg> 或 xlink:href="javascript:..."
- 永远不要信任用户提供的 SVG 字符串,无论它看起来多“干净”
- 禁用所有基于字符串拼接的插入方式(
innerHTML、insertAdjacentHTML、模板字面量直插) - 若必须动态渲染 SVG 内容,优先走
<img src="xxx.svg">—— 浏览器会将其作为资源加载,不执行脚本
DOMPurify 是目前最可靠的 SVG 白名单净化方案
DOMPurify 不是简单删标签,而是按 W3C SVG 规范构建白名单:只保留 <path></path>、<circle></circle>、<rect></rect> 等绘图元素,自动剥离 <script></script>、<foreignobject></foreignobject>、<animate></animate>,并过滤所有 on* 属性和危险 href 值(如 javascript:、data:)。
关键配置必须显式启用 SVG 支持:DOMPurify.sanitize(svgString, { USE_PROFILES: { svg: true } })
- 不加
{ USE_PROFILES: { svg: true } },默认只净化 HTML,SVG 标签全放行 - 避免自己写正则或黑名单过滤 ——
<svg><g onload="alert(1)"></g></svg>、<svg><style>@import url(javascript:...)</style></svg>都能绕过 - 净化后仍需校验输出是否为空或仅含安全标签;若返回空字符串,说明原始内容被全删,应拒绝渲染
服务端 SVG 文件上传必须做结构级清洗,不能只验 MIME 或后缀
前端限制 .svg 后缀、后端检查 Content-Type: image/svg+xml 或文件头,完全无效。攻击者可构造合法 SVG 头 + 恶意脚本,getimagesize() 和 filetype() 全部识别为“有效图像”。
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
真正有效的做法是:用 XML 解析器加载 SVG,禁用外部实体,再遍历 DOM 删除高危节点和属性:
- 移除所有
<script></script>、<foreignobject></foreignobject>、<handler></handler>、<set></set>、<animate></animate>元素 - 删除所有以
on开头的属性(onclick、onload、onmouseover…) - 过滤
xlink:href和href属性值:禁止javascript:、data:、vbscript:协议 - 对
style属性做严格校验,禁用expression()、url(javascript:...)
Python 示例(使用 xml.etree.ElementTree):parser = ET.XMLParser(resolve_entities=False)tree = ET.fromstring(svg_bytes, parser=parser) —— 关键是 resolve_entities=False 防 XXE
静态展示场景下,直接转 PNG 是最彻底的防御
如果用户上传的 SVG 只用于头像、图标、封面图等纯展示用途,根本不需要保留矢量能力。此时最安全的做法是:服务端接收 SVG 后,立即用无沙箱风险的渲染器(如 resvg CLI 或 Puppeteer headless)转成 PNG,存储 PNG,丢弃原始 SVG。
- 转换过程必须设超时(如 5s)和内存上限(如 100MB),防止恶意 SVG 触发无限循环或 OOM
- 生成的 PNG 要验证二进制头是否为
\x89PNG\r\n\x1a\n,并检查尺寸是否在合理范围(如 ≤ 2000×2000) - 绝不将原始 SVG 文件存为静态资源并允许直接访问 —— 即使加了 CSP,
image/svg+xml类型仍可被<object></object>或直接打开执行脚本
真正麻烦的不是技术实现,而是开发习惯:很多人默认“SVG 就是图”,却忘了它本质是带 DOM 的 XML 文档。只要存在“解析并渲染”这个动作,就必须按代码级安全标准对待 —— 而不是按图片处理。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










