为何严格CSP下"script.text = ..."不被视为不安全?
为什么动态创建script标签注入代码不会被严格CSP拦截?
嘿,这个问题问得特别到位!很多刚接触内容安全策略(CSP)的开发者都会搞混这两种代码注入方式的区别,咱们一步步拆解清楚:
首先得明确:你列出来的那些被严格CSP拦截的行为(eval()、Function()、带字符串参数的setTimeout等),都属于运行时动态编译执行字符串代码的范畴,CSP把这类行为归到unsafe-eval的管控规则里,默认严格模式下直接拦截。
举个例子,eval(badCode)的本质是把badCode这个字符串当作代码,直接在当前执行的作用域里即时编译并运行——这种行为太容易被XSS攻击利用了,所以CSP把它列为高危操作。
那动态创建script标签的代码为啥不在这个列表里?因为它和eval(badCode)的执行机制完全不一样:
var script = document.createElement('script'); script.text = badCode; document.head.appendChild(script);
这段代码的本质是创建了一个内联脚本元素,然后把代码作为这个元素的内容插入到DOM中执行,它属于CSP里unsafe-inline的管控范畴,和unsafe-eval是两条完全不同的规则线:
- 这类脚本的执行上下文是全局作用域,相当于在页面里新增了一段内联
<script>标签; - 如果你的CSP设置了严格的
script-src 'self'(没有添加unsafe-inline),那这段代码其实也会被拦截,但它被拦截的原因是违反了“禁止内联脚本”的规则,而不是“禁止动态执行字符串代码”的规则——这就是它不在你之前列出的那组被拦截行为里的核心原因。
简单总结下:两者的核心区别在于代码执行的机制,eval是在当前运行流程里直接解析字符串代码,而动态创建script标签是新增一个独立的脚本资源来执行代码,CSP用两套不同的规则分别管控它们,所以前者归为unsafe-eval,后者归为unsafe-inline,自然不会出现在同一组“不安全”列表里。
内容的提问来源于stack exchange,提问作者Brandon
相关产品推荐
相关产品推荐

