真正有效的xss整改必须拆解到输入、解析、输出三环节并强制模块级校验;escapehtml仅局部生效,自定义插件、v-pre区域、markdown片段易绕过;需属性级控制(禁on*事件、限href/src协议、过滤危险css);输出须按上下文编码(html/js/url/json不同策略);动态html必须用domparser校验并封装纯函数。

直接在 HTML 中写死安全策略或只靠单点转义,90% 的 XSS 仍会漏过;真正有效的整改必须把策略拆解到输入、解析、输出三个环节,并强制模块级校验。
escapeHtml 调用是否覆盖所有渲染路径
docsify 的 escapeHtml 确实能转义 、<code>>、"、'、&,但它只在特定位置生效:比如 src/core/render/utils.js 中的文本节点处理,或 media.js 里对 iframe src 的赋值:html:`<iframe src="%24%7BescapeHtml(url)%7D"></iframe>`。
常见错误现象:
- 开发者自定义插件中直接拼接 HTML 字符串,绕过了 core 渲染流程,
escapeHtml完全不生效 -
v-pre或data-ignore标记区域被跳过解析,用户输入原样插入 DOM - Markdown 解析后生成的 HTML 片段(如表格、代码块)若未走统一净化通道,可能含未转义属性
HTML 标签白名单是否严格限制危险属性
仅过滤标签(如禁止 <script></script>)远远不够。攻击者更常利用 <img src="https://img.php.cn/?x-oss-process=image/resize,p_40" alt="结合全局安全策略的前端HTML代码质量防御性整改"> 这类“合法”标签 + 危险事件属性的方式触发 XSS。
审查重点应落在属性级控制:
- 是否禁用全部事件处理器:
onerror、onclick、onload、onmouseover等以on开头的属性必须被剥离 - 是否限制
href和src的协议白名单?仅允许http://、https://、data:image/,拒绝javascript:、vbscript:、data:text/html -
style属性是否受限?expression()、url(javascript:)等 CSS 注入手法需被识别并清除
输出上下文决定编码方式,不能统一用 HTML 实体转义
同一个用户输入,在不同位置需要不同处理:插入到 HTML 文本节点、作为属性值、嵌入到 JavaScript 字符串、写入 URL 参数,安全要求完全不同。
典型误用:
- 把所有输出都套用
escapeHtml(),但当用户输入被插进<script>var name = "${name}";</script>时,仅 HTML 转义无法阻止闭合引号后执行任意 JS - 在 URL query 中直接拼接未编码的用户输入,导致
location.href = '/search?q=' + userInput被注入q=xxx%22%3E%3Cscript%3E - JSON 输出未使用
JSON.stringify()而是手动拼字符串,遗漏对\u2028、\u2029的处理,引发 JS 解析中断或注入
模块加载阶段是否强制 DOMParser 校验动态 HTML
直接在 innerHTML 中插入未经校验的动态 HTML,是前端最危险的代码缺陷——它不报错、不中断执行,却可能让整个页面结构崩坏、脚本失效、甚至引入 XSS。
关键实操建议:
- 所有负责渲染的模块(如
renderer.js)应在顶层import后立即定义校验函数,不依赖外部状态 - 校验必须使用
DOMParser().parseFromString(htmlStr, 'text/html'),而非正则或字符串判断——只有解析器能真实模拟浏览器行为 - 若
doc.body.children.length === 0 && htmlStr.trim()非空,说明 HTML 结构严重损坏,应直接throw错误,阻断后续执行 - 服务端返回的 HTML 片段(如
<p>Hello</p> <div class="meta"></div>)必须强制包裹一层根节点,否则DOMParser会丢弃无父级的并列节点
最容易被忽略的一点:校验逻辑必须封装在 ES 模块中导出纯函数(如 safeHtmlParse),禁止跨模块隐式传递 HTML 字符串——一旦形成 A.generateCardHtml() → B.innerHTML = ... 这种契约,错误堆栈永远指向调用方,而问题根源藏在加载链路深处。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











