base标签会绕过CSP对相对URL的控制,必须配置base-uri指令;base-uri 'self'或'none'可限制base行为,且须通过HTTP响应头设置,否则CSP在路径解析环节完全失效。

base 标签和 CSP 不是“能不能共存”的问题,而是 base 会直接绕过 CSP 对相对 URL 的控制逻辑——不配 base-uri 指令,等于主动交出路径解析权。
为什么 base 标签会让 CSP 失效一大半
浏览器在解析 <img src="/avatar.jpg">、<a href="/logout">、<form action="/api/submit"> 这类相对路径时,完全依赖 <base href="..."> 的值来拼接完整 URL。CSP 的 img-src、form-action、connect-src 等指令只校验最终拼出来的目标地址,但拼接过程本身不受控。
常见错误现象:
- 页面写了
<base href="https://evil.com">,所有相对路径请求都发往恶意域名,而 CSP 并未拦截——因为img-src 'self'无法阻止浏览器把/avatar.jpg解析成https://evil.com/avatar.jpg - 前端框架(如 Vue SSR)自动注入
<base href="/">,但部署在子路径(如/app/)时,base值未同步更新,导致资源 404,开发者误以为是script-src配错
base-uri 指令不是可选项,是必须项
只要 HTML 中存在 <base> 标签,就必须显式配置 base-uri,否则 CSP 对路径解析环节完全失能。
立即学习“前端免费学习笔记(深入)”;
-
base-uri 'self':只允许<base href="https://yoursite.com">或同协议同域的绝对 URL;<base href="/subpath">这种相对值会被拒绝 -
base-uri 'none':禁止任何<base>标签,浏览器直接忽略它;适合想彻底切断路径劫持风险的场景 -
base-uri不支持'unsafe-inline'或通配符;base-uri https://trusted.com合法,但base-uri *.com无效
注意:base-uri 必须通过 HTTP 响应头配置,<meta http-equiv="Content-Security-Policy"> 在 Chrome 124+ 及主流 Android WebView 中已不支持该指令。
base 和 script-src 'strict-dynamic' 冲突极容易被忽略
当使用 strict-dynamic 构建信任链时,<base> 会影响动态创建脚本的源判定逻辑:
- 若初始
<script nonce="abc">加载后执行document.write('<script src="/chunk.js"></script>'),浏览器会用<base>的值解析/chunk.js,再比对是否在script-src白名单中 - 如果
<base href="https://cdn.example.com">,但响应头里没写script-src https://cdn.example.com,即使有'strict-dynamic',/chunk.js也会被拦 - Webpack/Vite 构建产物若含服务端注入的
<base>,且未在构建时预置 CDN 域名到 CSP 头中,上线后动态加载的 chunk 就会静默失败
真正难的不是写对 base-uri,而是确认整个应用生命周期里——包括 SSR 渲染、CDN 缓存、微前端子应用、以及第三方 SDK 注入的任意 HTML 片段——是否都遵守同一套 <base> 规则。漏掉一个,攻击面就重新打开。



















