CORB是浏览器自动启用的安全机制,用于阻止<script>或<img>等标签加载跨域的非预期MIME类型资源(如text/html、application/json),防止XSSI等攻击;它会清空响应体并移除响应头,而fetch/XHR因受CORS控制不受其影响。

CORB 不是你要“制作”的东西,它是浏览器自动运行的安全机制。你无法用 HTML 写出一个“CORB 读取阻止”,但你可以让自己的页面不触发它——关键在于别让 <script> 或 <img> 去加载非预期 MIME 类型的跨域资源。
为什么 <script src="https://xxx.com/api/data"> 会触发 CORB?
CORB 的触发条件很具体:当浏览器发现你用 <script> 标签请求了一个本该返回 application/javascript 的 URL,但服务器实际返回了 text/html(或 application/json、text/xml),它就会拦截响应体,把内容清空、头抹掉,只留状态码 200。
常见诱因包括:
- 误把后端 API 接口当 JS 文件用,比如写成
<script src="/user/profile">,而该接口返回的是 HTML 页面或 JSON 字符串 - 第三方统计/埋点脚本地址写错,指向了一个 HTML 路由(如
/stat?uid=123)而非真正的像素 GIF 或 JS 端点 - 服务端未配置正确
Content-Type响应头,比如 PHP 脚本没调用header('Content-Type: image/gif');,却用<img src="/track.php">加载
fetch() 和 XMLHttpRequest 为什么不受 CORB 影响?
CORB 只作用于“历史遗留的、无 CORS 保护的加载上下文”,比如 <script>、<img>、<link>、<iframe>。而 fetch() 和 XMLHttpRequest 天然受同源策略和 CORS 控制——它们根本不会发起跨域读取,除非服务器明确返回 Access-Control-Allow-Origin。
立即学习“前端免费学习笔记(深入)”;
所以如果你需要读取跨域 text/html 内容(比如爬取公开页面摘要),必须走 fetch() + 后端代理,不能靠前端直接 <script> 加载。
注意:fetch() 请求本身不会被 CORB 拦,但若你把它“伪装”成 script 加载(比如动态创建 <script> 并设 src),那就又回到 CORB 触发路径了。
如何快速验证是不是 CORB 而不是 CORS?
打开 Chrome DevTools → Network 面板,找到那个报 CORB 的请求,点开看:
- 状态码是
200(说明服务器确实响应了) - Preview / Response 标签页为空(CORB 已清空响应体)
- Response Headers 里看不到任何头(CORB 已移除全部响应头)
- Console 报错明确含
Cross-Origin Read Blocking (CORB) blocked cross-origin response和MIME type text/html
如果以上都符合,基本可排除 CORS 配置问题——CORS 失败时状态码通常是 0 或报 net::ERR_FAILED,且 Network 面板里该请求会标红、没 Preview。
CORB 的核心逻辑藏在浏览器渲染进程隔离层,开发者能做的只有两点:别用错标签加载资源;对真正需要跨域读取的场景,老老实实用 fetch() + 服务端代理。最容易被忽略的是——你以为只是加个 <img> 上报数据,结果后端返回了 HTML,CORB 就默默把响应吞了,连错误都不抛,只留一个 console warn。这种静默失败,比报错更难排查。

















