HTTPQUERY
English

X-Content-Type-Options

用法

MIME 嗅探是一种浏览器行为,浏览器会检查响应内容,并根据响应正文中找到的模式覆盖声明的 Content-Type。虽然其本意是为配置错误的服务器提供便利,但 MIME 嗅探却打开了一个安全漏洞:攻击者上传一个伪装成图像的文件,浏览器将内容嗅探为 HTML 或 JavaScript,于是跨站脚本攻击得以执行。

X-Content-Type-Options 头部封堵了这个漏洞。当设为 nosniff 时,浏览器会严格遵循 Content-Type 头部,并拒绝加载声明类型与预期类型不符的资源。对于样式目标,除非 Content-Type 为 text/css,否则浏览器会阻止该响应。对于脚本目标,除非 Content-Type 是有效的 JavaScript MIME 类型,否则浏览器会阻止该响应。

该头部作为一项标准的安全加固措施被广泛部署,推荐与 Content-Security-Policy 和 X-Frame-Options 一同使用以实现纵深防御。

nosniff

nosniff 值是唯一定义的值。设置此指令可防止浏览器将响应从声明的 Content-Type 进行 MIME 嗅探。

示例

服务器在禁用 MIME 嗅探的情况下提供 JSON API 响应,确保浏览器严格将响应视为 JSON:

Content-Type: application/json
X-Content-Type-Options: nosniff

以正确的 Content-Type 和嗅探保护提供的 CSS 文件,防止浏览器重新解读该文件:

Content-Type: text/css
X-Content-Type-Options: nosniff

疑难解答

被 nosniff 阻止的资源会产生控制台错误,引用声明的 Content-Type 与该资源目标的预期类型之间的 MIME 类型不匹配。

脚本因 MIME 类型不匹配而被阻止。浏览器会记录 Refused to execute script from ’…’ because its MIME type (‘text/plain’) is not executable。当服务器发送的 JavaScript 文件带有非有效 JavaScript MIME 类型(text/javascript、application/javascript)的 Content-Type 时,会发生这种情况。请修正服务器配置。在 nginx 中,确认 http 块中出现 include mime.types;。在 Apache 中,验证配置或 .htaccess 中存在 AddType text/javascript .js。

由于 nosniff 下 MIME 类型错误导致 CSS 未生效。控制台显示 Refused to apply style from ’…’ because its MIME type (‘text/html’) is not a supported stylesheet MIME type。服务器将 CSS 文件作为 text/html 或 text/plain 而非 text/css 发送。在 nginx 中,添加 types { text/css css; } 或包含默认的 mime.types 文件可解决此不匹配。在 Apache 中,将 AddType text/css .css 添加到服务器配置中。

服务器为静态文件发送错误的 Content-Type。配置错误的服务器、CDN 或对象存储(S3、GCS)常将静态文件作为 application/octet-stream 或 text/plain 提供。请通过 DevTools 的 Network 选项卡选择该请求并检查响应头,来检查每个资源的 Content-Type。对于 S3,请在上传时设置 ContentType 元数据。对于经 CDN 提供的资源,请验证源站返回正确的类型,因为大多数 CDN 会原样透传源站的 Content-Type。

在 DevTools 控制台中诊断被阻止的资源。打开 Console 选项卡并筛选 MIME 相关的错误。每条被阻止资源的消息都包含 URL、声明的 MIME 类型和预期类型。请与 Network 选项卡交叉核对:选择被阻止的请求,打开 Headers 面板,并检查 Content-Type 响应头。修复方法始终是在服务器上更正 Content-Type,而非移除 nosniff 头部。

配置

对所有响应应用 nosniff。开销可忽略不计,而保护覆盖脚本、样式和其他子资源。

nginx:

add_header X-Content-Type-Options nosniff always;

Apache:

Header always set X-Content-Type-Options nosniff

IIS(web.config):

<code class="language-xml"><customHeaders>
  <add name="X-Content-Type-Options"
       value="nosniff" />
</customHeaders>