dom型xss不经过服务端,innerhtml、document.write、eval等操作直接解析执行用户输入的html/js,csp和后端过滤均无效;必须对location.search、localstorage等不可信源数据严格净化或改用textcontent,富文本渲染须经dompurify白名单过滤。

DOM型XSS不经过服务端,innerHTML、document.write、eval 这类操作一旦拼接用户输入,就直接执行——CSP拦不住,后端过滤也无效。
为什么 document.write 和 innerHTML 是高危操作
这两者会把字符串当作 HTML 解析并插入 DOM,浏览器不区分“内容”和“代码”。只要字符串里含 <img src="x" onerror="alert(1)"> 或 <script>fetch('/steal?c='+document.cookie)</script>,就会立刻触发。
-
document.write在页面加载完成后调用会清空整个文档,且无法被 CSP 限制执行逻辑 -
innerHTML = userContent不做转义时,等于主动执行用户提供的任意 HTML + JS - 即使你过滤了
<script></script>,<svg onload="..."></svg>、<a href="javascript:..."></a>照样生效
location.search / location.hash 直接赋值给 innerHTML 的典型错误
单页应用里常见这种写法:document.getElementById('content').innerHTML = new URLSearchParams(location.search).get('t')。攻击者只要访问 ?t=<img src="x" onerror="alert(1)"> 就完成攻击。
- 所有从
location.search、location.hash、URLSearchParams、localStorage读取的值,都应视为不可信输入 - 不要用
innerHTML渲染这些值;改用textContent(纯文本)或innerText(带样式渲染但不执行脚本) - 如果必须渲染富文本,先过
DOMPurify.sanitize(),禁用on*事件和javascript:协议
JSON.parse 后直接 innerHTML 的隐性风险
前端常从 API 拿到 JSON 数据,比如 { title: '<img src="https://img.php.cn/?x-oss-process=image/resize,p_40" alt="HTML安全性防范:规避XSS跨站脚本攻击的DOM安全编写方法">' },然后写成 el.innerHTML = data.title——这和直接拼 URL 参数没区别。
- JSON 数据来源不可控(后端未编码、中间代理篡改、CDN 缓存污染),不能默认“安全”
- 哪怕数据来自自己后端,也要按输出上下文处理:插入 HTML 用 HTML 实体转义,插入
<script></script>内部用JSON.stringify(),作为 URL query 用encodeURIComponent() - 推荐统一用模板函数封装,例如:
htmlEscape(str)对应 HTML 上下文,jsStringEscape(str)对应 JS 字符串上下文
React/Vue 等框架为何“自动防XSS”但仍有漏网之鱼
框架默认对 {userInput} 做 HTML 转义,但绕过机制明确存在:React 的 dangerouslySetInnerHTML、Vue 的 v-html、Svelte 的 {@html} ——这些 API 的设计初衷就是“你要自己负责”。
- 只要用了
dangerouslySetInnerHTML,你就得确保传入的__html已经过DOMPurify.sanitize()或等效处理 - 不要在
v-html中拼接变量:v-html="userInput + '更多文字'"是危险的,因为拼接破坏了原始转义 - 框架不处理
eval()、setTimeout(string)、setInterval(string),这些仍是 DOM 型 XSS 入口
DOM型XSS的修复不在输入端,而在每个动态插入点——你永远不知道哪一行 innerHTML 会被 URL 参数、localStorage 或接口响应悄悄喂进恶意内容。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











