svg xss风险源于加载与解析方式,内联插入未净化svg可执行脚本;应使用dompurify配合svg白名单净化,优先采用引入,服务端需xml解析+标签属性过滤,并配置csp策略如object-src 'none'。

直接在页面中渲染用户提供的SVG,是前端XSS高发场景之一。关键不在SVG本身,而在它被如何加载、解析和插入——只要允许执行脚本或响应事件,就可能触发攻击。
内联SVG必须净化后再插入
用 innerHTML、document.write() 或模板引擎直接写入未处理的SVG字符串,等于开放JS执行入口。以下结构都能弹窗:
<svg onload="alert(1)"></svg><svg><script>fetch('/steal-cookie')</script></svg><svg><g onclick="location='https://evil.com'">点我</g></svg>
解决办法不是简单删掉 <script></script> 标签,而是用 DOMPurify 配合 SVG 白名单配置:
DOMPurify.sanitize(svgString, { USE_PROFILES: { svg: true } });
它会递归清理 on* 属性、<foreignobject></foreignobject>、<script></script>、危险的 xlink:href 等,比正则可靠得多。
加载方式决定风险等级
不同引入方式的安全性差异很大:
-
<img src="icon.svg">—— 安全。浏览器禁止脚本执行,纯展示 -
<object data="chart.svg" type="image/svg+xml"></object>—— 危险。支持脚本、事件、同源访问 -
<iframe src="logo.svg"></iframe>—— 危险。完整上下文,可跨域通信(若同源) - CSS 中
background-image: url(icon.svg)—— 一般安全,但需防url(javascript:...)注入
优先选 <img>;需要交互时,改用 Canvas 动态绘制,或用 D3/Snap.svg 等库生成干净 SVG 元素。
服务端处理上传的SVG要双重校验
用户上传的 .svg 文件不能只看后缀或 MIME 类型。必须:
- 用 XML 解析器加载,并禁用外部实体(防 XXE)
- 遍历 DOM,移除
<script></script>、<foreignobject></foreignobject>、<animate></animate>等高危标签 - 过滤所有以
on开头的属性(onclick、onload…) - 校验
href和xlink:href值,拒绝javascript:、data:、http://等协议 - 必要时转成 PNG 存储,彻底剥离 XML 可执行能力
前端环境加一层内容安全策略(CSP)
即使做了净化,CSP 是兜底防线。建议设置:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; img-src 'self' data:; style-src 'self' 'unsafe-inline'
其中 object-src 'none' 能直接阻断 <object></object> 加载 SVG 脚本,script-src 限制内联脚本执行,对防御绕过类攻击很有效。











