HTML解析器对HTML注释内嵌恶意脚本的扫描及阻断逻辑

作者:袖梨 2026-06-18
HTML注释不是安全机制,仅是语法占位符;浏览器解析器跳过注释内容而不执行,不等于拦截恶意脚本;真正防护需依赖textContent、DOMPurify净化或CSP策略。

HTML解析器本身不扫描、不识别、也不阻断注释里的“恶意脚本”——它只按规范把<!---->之间所有内容当作纯文本跳过,既不解析,也不执行,更不校验安全性。

浏览器原生解析器根本不管“恶意”与否

Chrome、Firefox等浏览器的HTML解析器(Blink/Gecko)在遇到<!--时,会直接进入“注释状态”,直到匹配到-->为止。中间所有内容,包括<script></script>javascript:alert(1)、甚至嵌套的<!--,都按字符流原样吞掉,不做语法分析,不构建DOM节点,不触发任何事件。

这意味着:

  • 你手写<!-- <script>alert(1)</script> -->,它真不会执行——但这只是因为被跳过了,不是因为“被拦截”
  • 如果用户输入能控制输出位置,比如拼接出--><script>steal()</script><!--,浏览器会先退出注释,再解析并执行脚本
  • 不存在“扫描注释内容是否含危险关键词”的逻辑;解析器连正则都不跑,更别说语义分析

为什么有人误以为注释能防XSS

这种误解常来自两个混淆点:

立即学习“前端免费学习笔记(深入)”;

  • 看到<!-- <script>...</script> -->没执行,就以为“注释起了防护作用”——其实只是碰巧没被注入点利用
  • 把后续环节(如DOMPurify净化、CSP策略、或手动textContent赋值)的防护效果,错误归因到HTML注释上

真实防御链里,注释连“第一道防线”都算不上——它连防线都不是,只是个语法占位符。

真正起作用的安全机制在哪

如果你在注释里塞了脚本却没被运行,功劳不在<!--,而在以下某处:

  • 服务端用了DOMPurify.sanitize(),它会遍历整个DOM树,主动移除script标签,无论是否在注释内(注释节点本身也会被保留,但其中的脚本不会复活)
  • 页面启用了CSP,且配置了script-src 'self'和禁用'unsafe-inline',导致即使脚本被意外注入并解析,也会被运行时拦截
  • 前端用element.textContent = userHtml而非innerHTML,天然规避所有HTML解析,注释和脚本全当字符串处理

注意:htmlparser2这类库的decodeEntities: true选项,也只影响实体解码行为,不会额外检查注释内容。

别把注释当安全边界

最易被忽略的一点:HTML注释不是沙盒,也不是过滤器。它不提供任何上下文隔离能力。一旦攻击者能控制输出拼接方式(比如模板引擎未转义变量、innerHTML直插用户数据),注释边界随时可被-->闭合绕过。

真正该做的,是让不可信数据永远不进入HTML解析流程——要么走textContent,要么经DOMPurify白名单净化,要么靠CSP兜底。指望

相关文章

精彩推荐