HTML中CSP的img-src指令管控图片加载来源

作者:袖梨 2026-06-08
img-src指令检查浏览器加载<img>标签外部图片资源的行为,仅对非内联、非data:协议的src值生效,如HTTPS、HTTP、协议相对URL及同源绝对路径;data:URL需显式配置img-src data:才受控,而blob:、CSS background-image等不直接受其约束。

img-src 指令到底检查哪些行为

浏览器对 <img> 标签的 src 属性值做 CSP 校验,仅当该值是**非内联、非 data: 协议的外部资源**时才触发 img-src 检查。也就是说,以下情况都会走 img-src 策略:

  • <img src="https://cdn.example.com/logo.png"> —— 外部 HTTPS 图片
  • <img src="//static.site.com/icon.svg"> —— 协议相对 URL
  • <img src="/assets/avatar.jpg"> —— 同源绝对路径(受 'self' 控制)
  • <img src="http://insecure.img.net/photo.gif"> —— HTTP 资源(若策略未显式允许 http:,会被拦截)

但这些不会触发 img-src 检查:

  • <img src="data:image/png;base64,iVBOR...> —— data:URL 受 data: 值控制,不是 img-src 的默认管辖范围(除非你显式写了 img-src data:
  • CSS 中的 background-image: url(...) —— 这归 style-srcimg-src 共同作用,但实际由 img-src 主导(规范要求)
  • <picture><source>srcset —— 同样受 img-src 约束

常见 img-src 配置值与实际效果差异

写错一个引号或漏掉冒号,图片就全挂了。真实线上环境里,最常踩的坑是把值当字符串写死,没加引号,或者混淆了指令层级。

  • img-src 'self':只允许同协议+同域名+同端口,https://a.com/1.jpg 不能加载 http://a.com/2.jpg(协议不匹配)
  • img-src https::允许任意 HTTPS 图片,但禁止 'self' 的相对路径(如 /img/x.png),因为 https: 不包含 'self'
  • img-src * :允许所有来源,但不包括 data: 和 blob: —— 这是 CSP 规范的硬性限制,* 明确排除 data: 和 protocol-relative URL
  • img-src 'self' data::明确放行同源资源 + data:URL,适合用 base64 头像或图标字体场景
  • img-src 'none':连 <img src="/logo.svg"> 都会失败,页面上所有 <img> 直接不渲染(控制台报 Refused to load the image

为什么设置了 img-src 却还有图片被拦截?

根本原因往往是策略没覆盖完整加载链路,或被更高优先级指令覆盖。CSP 是“最小权限”模型,指令之间有继承和 fallback 关系。

立即学习“前端免费学习笔记(深入)”;

  • 如果没配 img-src,浏览器会 fallback 到 default-src —— 所以 default-src 'none' 但漏写 img-src,图片照样挂
  • <img src="blob:http://site.com/xxx"> 不受 img-src 控制,而是由 connect-srcscript-src(取决于 blob 来源)间接影响
  • 使用 <img src="https://third-party.com/a.jpg" referrerpolicy="no-referrer"> 不影响 CSP 校验,但某些 CDN 会因缺失 referrer 拒绝响应,看起来像被 CSP 拦了(其实是 403,不是 CSP violation)
  • 开发工具 Network 面板看到 404 或 CORS error,不是 CSP 问题;只有 Console 出现 Refused to load the image + violates the following Content Security Policy 才是真 CSP 拦截

如何快速验证 img-src 是否生效

别等上线才发现——本地就能模拟,而且要测「边界情况」。

  • 在 HTML head 中加:
    <meta http-equiv="Content-Security-Policy" content="img-src 'self';">
    ,然后放一个 <img src="https://example.com/test.jpg">,看是否报错
  • 用 curl 测响应头:curl -I https://yoursite.com/,确认返回头含 Content-Security-Policy: img-src 'self'(注意大小写和空格)
  • 打开 DevTools → Application → Content Security Policy,Chrome 会直接列出当前生效的各指令及违规记录
  • 故意触发一次违规(比如临时改成 img-src 'none'),再看 Console 是否出现 report-urireport-to 发出的 JSON 报告(需配置了上报)

真正容易被忽略的是:CSP 策略对 <img> 的约束是静态的,它不管图片内容是否合法,也不校验 MIME 类型或文件头 —— 所以哪怕你放行了恶意域名,只要图片本身是 PNG,浏览器照常解码渲染。防护 XSS 不能只靠 img-src,得配合服务端校验和输出编码。

相关文章

精彩推荐