X-Content-Type-Options
X-Content-Type-Options:nosniff 防止浏览器对响应内容进行 MIME 嗅探,强制按 Content-Type 声明处理。
#type / concept
#status / evergreen
#tech / security
#resource / http
#platform / browser
[!info] related notes
- 所属 MOC: security-moc
- 总览: http-response-headers
- 关联概念: http-content-description-headers(Content-Type)
- 并列安全头: CSP, HSTS, x-frame-options, referrer-policy, permissions-policy
X-Content-Type-Options
一句话定义
X-Content-Type-Options: nosniff 告诉浏览器:不要猜测响应的 MIME 类型,严格按照 Content-Type 声明处理。
它要解决什么问题
浏览器有一种行为叫 MIME sniffing(类型嗅探):当服务器没有明确声明 Content-Type,或者声明的类型和实际内容”看起来不一致”时,浏览器会自己猜测内容类型并按猜测结果处理。
这可能导致安全问题:
服务器声明 Content-Type: text/plain
但响应体内容看起来像 HTML
浏览器猜测它是 HTML 并渲染执行
如果内容中包含恶意脚本 → XSS
核心机制
Content-Type: application/json; charset=utf-8
X-Content-Type-Options: nosniff
设了 nosniff 后:
- 如果
Content-Type是text/html、application/javascript、image/*等已知类型,浏览器严格按声明处理 - 如果类型不匹配,浏览器直接拒绝,而不是猜测
受影响的场景
浏览器对以下 MIME 类型会做 sniffing 检查(设了 nosniff 后):
text/htmltext/xmlapplication/xmlapplication/javascriptimage/*等
对于 text/plain、application/octet-stream 等,nosniff 的行为因浏览器而异。
推荐配置
建议常开。几乎所有现代 Web 应用都应该设置:
X-Content-Type-Options: nosniff
单独使用没有意义,必须配合正确的 Content-Type:
Content-Type: application/json; charset=utf-8
X-Content-Type-Options: nosniff
常见场景
场景 1:API 返回 JSON 但 Content-Type 写错
# 错误
Content-Type: text/html
X-Content-Type-Options: nosniff
{"error": "not found"}
如果 HTML CSP 不允许 inline script,浏览器可能拒绝渲染这段”HTML”。正确做法是设 Content-Type: application/json。
场景 2:用户上传文件被下载时
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="data.csv"
X-Content-Type-Options: nosniff
防止浏览器把用户上传的 CSV 文件当成 HTML 渲染(如果内容中包含恶意 HTML)。
边界与易混淆点
- nosniff 不是”禁止执行脚本”:它只管类型嗅探,脚本执行由 CSP 控制。
- nosniff 不影响正常的 Content-Type:如果 Content-Type 正确,nosniff 只是多一层保险。
- 它是单值头:只有
nosniff一个有效值,不存在其他选项。 - 所有主流浏览器都支持:Chrome、Firefox、Safari、Edge 均支持。