识别XSS风险的关键是用户输入未经净化即回写DOM并被localStorage固化,形成可重复触发的DOM型漏洞;需检查contenteditable内容是否原样存入localStorage、恢复时是否直接innerHTML渲染、有无过滤危险片段。

识别这类 XSS 风险,关键不是“有没有用 contenteditable”,而是看用户输入是否未经净化就回写进 DOM,且该过程绕过了服务端校验、又恰好被 localStorage 等本地存储“固化”下来——形成可重复触发的 DOM 型漏洞。
重点检查 contenteditable + localStorage 的数据流向
当页面把用户在 contenteditable 区域编辑的内容(含 HTML)存入 localStorage,再在后续加载时直接用 innerHTML 或 insertAdjacentHTML 渲染出来,就构成典型风险链。需逐环节确认:
- 用户输入是否被
localStorage.setItem('draft', el.innerHTML)类方式原样保存? - 页面初始化或恢复草稿时,是否用了
el.innerHTML = localStorage.getItem('draft')? - 是否对读出的内容做过滤?比如没调用
DOMPurify.sanitize(),也没移除<script>、onerror、javascript:等危险片段?
警惕“看似安全”的绕过点
有些实现会误以为“没服务端参与就不算 XSS”,但 DOM 型 XSS 不依赖后端。常见疏漏包括:
- 只过滤了
<script>标签,却放行了<img src=x onerror=alert(1)>或<a href="javascript:alert(1)"> - 用
innerText显示内容,但渲染预览层时又切回innerHTML—— 两者不一致导致过滤失效 - 依赖
contenteditable="plaintext-only",但它仅限制浏览器默认格式操作,无法阻止用户粘贴恶意 HTML
用 Trusted Types 快速验证防护是否生效
若站点已启用 Trusted Types(现代浏览器支持),可直接检查控制台是否报错:
立即学习“前端免费学习笔记(深入)”;
- 打开开发者工具 → Console,刷新页面
- 如果出现类似
Failed to set an illegal value on 'innerHTML'的错误,说明 Trusted Types 正在拦截不安全赋值,防护有效 - 若无报错,且页面能成功渲染用户存的富文本,则需人工审计
innerHTML赋值点是否接入了 Trusted Type policy
实际检测建议:模拟攻击路径验证
在测试环境手动走一遍闭环流程,比静态扫描更可靠:
- 在
contenteditable区域输入:<img src=x onerror=alert(document.domain)> - 点击“保存草稿”(触发
localStorage.setItem) - 刷新页面,触发草稿自动加载
- 观察是否弹窗;若弹出,说明 DOM XSS 可利用



















