innerHTML直接拼接用户输入必然导致XSS,因浏览器会将其作为HTML解析并立即执行onerror、javascript:等恶意代码;即使使用正则转义,

为什么innerHTML直接拼接用户输入必然出事
因为浏览器会把字符串当作HTML重新解析,onerror、javascript:、data:这些值一旦出现在最终DOM里,就可能立即执行。哪怕你只漏掉一个iframe[sandbox]或a[href]没校验协议,攻击者就能绕过所有前端过滤。
- 不要用
innerHTML = userInput,哪怕加了正则替换——、<code>、<code>都会被解析成<code> - 不要相信“只过滤
<script></script>就行”,<img src="https://img.php.cn/" alt="HTML安全合规:防御DOM注入攻击的防护指南">一样触发 - 服务端转义(如
html.escape())和前端textContent必须同时存在:前者防模板直出漏洞,后者防JS动态渲染漏洞
DOMPurify配置白名单时最常漏的三类属性
很多人以为配了ALLOWED_TAGS就安全了,其实ALLOWED_ATTRIBUTES才是高危区。DOMPurify默认禁用script等标签,但不会自动限制属性值协议或格式。
-
a[href]必须配合ADD_URI_SAFE_ATTR并显式声明只允https://、/、#开头,否则href="javascript:fetch('/api/leak')"照常运行 -
img[src]同理,要禁用data:和vbscript:协议,且alt属性不能省——漏配会导致img被当成空标签绕过校验 -
iframe即使不在ALLOWED_TAGS里,若sandbox被单独放进ALLOWED_ATTRIBUTES,就会启用沙箱逃逸能力,反而扩大攻击面
id/name属性污染全局作用域的真实风险
这不是理论漏洞,是浏览器默认行为:<input id="fetch">一加载,window.fetch就变成那个DOM节点,后续所有fetch()调用都会报错或静默失败。React/Vue组件里不暴露全局变量,但原生JS页面中极易中招。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 服务端渲染时,对用户输入的
id、name值强制加前缀,比如user_或哈希后缀id="user_f8a2b" - 前端动态插入必须用
document.createElement('div')+el.setAttribute('id', userInput),绝不能el.innerHTML += '<div id="' + userInput + '">' <li>禁用<code>document.write()——它会触发二次HTML解析,让id/name挂载逻辑重复执行,污染概率翻倍 - 净化后的字符串如果又被拼进模板引擎(如
<div>${sanitized}</div>),而模板关闭了转义({{ content | safe }}),等于跳过净化层 - 把净化结果传给
eval()、setTimeout()、location.href或Function(),这些API会重新激活JS执行上下文 - CSP无法拦截
onerror或javascript:伪协议,所以白名单漏配一个属性,CSP就完全失效;反过来,白名单再严,没配Content-Security-Policy响应头,base标签仍可劫持所有相对URL
白名单+DOMPurify ≠ 安全闭环,绕过点在哪
很多人把DOMPurify.sanitize(dirty)结果赋给innerHTML就以为万事大吉,其实只要后续操作踩中任意一条,整个防护就失效。
立即学习“前端免费学习笔记(深入)”;


















