为何代码未在控制台打印<script>alert(0)</script>反而输出console.log(str)到页面?
这是浏览器HTML解析器的标签匹配逻辑导致的:
当浏览器解析页面时,会逐字符扫描识别HTML标签。你代码里的</script>在HTML渲染时会被还原成</script>,而这个完整的闭合标签会被浏览器误判为当前<script>代码块的结束标记。
实际浏览器看到的代码结构是这样的:
<script> const str = '<script>alert(0)</script>' console.log(str) </script>
当解析到字符串里的</script>时,浏览器就认为当前脚本块已经结束,剩下的console.log(str)会被当成普通文本直接输出到页面body里,自然不会执行控制台打印的逻辑。
解决办法
有几种简单的方式可以规避这个问题:
拆分闭合标签:把字符串里的
</script>拆成两段,让浏览器识别不出完整的闭合标签:const str = '<script>alert(0)</scr' + 'ipt>' console.log(str)插入空字符串拆分标签:用模板字符串或者拼接空字符串的方式打断闭合标签的完整性:
const str = `<script>alert(0)</scr${''}ipt>` console.log(str)CDATA包裹(适合XML/XHTML场景):如果是在XHTML环境下,可以把JS代码放在CDATA块里,让解析器忽略内部的标签识别:
<script><![CDATA[ const str = '<script>alert(0)</script>' console.log(str) ]]></script>
内容的提问来源于stack exchange,提问作者Sao

