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>,<svg onload="...">、<a href="javascript:...">照样生效
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/" alt="HTML安全性防范:规避XSS跨站脚本攻击的DOM安全编写方法">' },然后写成 el.innerHTML = data.title——这和直接拼 URL 参数没区别。
立即学习“前端免费学习笔记(深入)”;
- JSON 数据来源不可控(后端未编码、中间代理篡改、CDN 缓存污染),不能默认“安全”
- 哪怕数据来自自己后端,也要按输出上下文处理:插入 HTML 用 HTML 实体转义,插入
<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 或接口响应悄悄喂进恶意内容。



















