script-src 'self'能拦截大部分XSS,因其在浏览器加载阶段拒绝执行非白名单来源脚本,包括内联脚本、onclick事件和javascript:伪协议,但无法防御DOM型XSS或未设其他指令导致的回退漏洞。

CSP 不能代替输出编码,但它是唯一能在浏览器加载阶段就阻断绝大多数XSS执行路径的机制。只要 script-src 配置正确且未退化,<script>alert(1)</script>、onclick=、javascript: 等常见注入几乎全部失效。
为什么只设 script-src 'self' 就能拦住大部分 XSS
浏览器默认允许内联脚本和 eval,而 CSP 的 script-src 指令直接覆盖这一行为。它不是“过滤”,而是“拒绝加载”——哪怕 HTML 已经被注入进 DOM,只要脚本没从白名单来源加载,就不会执行。
-
script-src 'self'拦截所有内联脚本:<script>alert(1)</script>、<div onclick="alert(1)">、<code><img onerror="..." alt="HTML内容安全策略在防止跨站脚本攻击中的核心应用" > - 同样拦截
javascript:协议:<a href="https://www.php.cn/link/e8644ee27d873e0bb207499b0279b8e8">click</a> - 但不拦
data:或 base64 编码的 JS(需额外加script-src 'unsafe-inline'才能执行,而这是必须避免的) - 服务端每次响应生成一个随机
nonce值,例如abc123,并写入响应头:Content-Security-Policy: script-src 'self' 'nonce-abc123' - 前端对应脚本必须带匹配属性:
<script nonce="abc123">console.log('ok')</script> - 注意:
nonce必须一次性且不可预测;Webpack/Vite 构建时若自动生成内联代码,需配置插件注入动态 nonce - 没设
object-src?Flash/Java 插件可能被载入并执行 JS(虽已淘汰,但旧系统仍存在) - 没设
base-uri?攻击者可插入<base href="https://evil.com/">,让所有相对路径脚本都指向恶意域 - 第三方统计 SDK(如百度统计、神策)未列入
script-src白名单?页面直接报错或功能异常,开发者常因此妥协加'unsafe-inline' - 使用
Content-Security-Policy-Report-Only上线却忘了切回强制模式?它只发报告,不拦截
nonce 是保留少量内联脚本的唯一安全方式
有些场景真绕不开内联脚本(比如 SSR 渲染后需要初始化状态),这时不能妥协加 'unsafe-inline',而应使用 nonce。
常见配置失效原因:default-src 回退陷阱与第三方 SDK 漏洞
很多人设了 script-src 'self' 却仍被绕过,往往是因为其他指令缺失导致浏览器“降级”执行宽松策略。
立即学习“前端免费学习笔记(深入)”;
CSP 最容易被忽略的点是:它只管“加载”,不管“解析执行”。DOM 型 XSS(比如 innerHTML = location.hash)完全绕过 CSP,因为没有外部资源加载——脚本是浏览器自己拼出来的。这时候,textContent、DOMPurify.sanitize() 和上下文感知编码才是唯一防线。



















