x-content-type-options 必须静态设置为 "nosniff",因浏览器仅识别该固定值,map 无法参与响应头输出且该头不支持动态或条件化取值。

不能通过 map 指令动态设置 X-Content-Type-Options 头。
为什么 map 无法用于 X-Content-Type-Options
map 是用于根据变量值生成新变量的指令,它本身不参与响应头输出,只提供变量供其他指令(如 add_header、proxy_cache_valid)使用。而 X-Content-Type-Options 必须是固定值 nosniff,浏览器只识别这一种有效取值;任何其他值(包括空值、""、off 或变量展开结果)都会被当作未设置,等同于关闭该安全机制。
- 该响应头不支持条件化或动态值,规范和所有主流浏览器(Chrome 13+、Firefox 50+、Safari 10+、IE 8+)均只认可且仅响应
nosniff -
add_header X-Content-Type-Options $some_var若$some_var不是字面量nosniff,实际发送的头将无效,安全策略失效 - 不存在“按请求类型启用/禁用 nosniff”的合理场景——该头的作用是全局约束浏览器行为,与 Content-Type 值本身无关
真正需要关注的 Content-Type 相关配置
如果你的意图是“对不同内容类型做差异化安全处理”,应聚焦在以下可落地的方向:
-
确保上游返回正确的 Content-Type:用
$upstream_http_content_type配合map校验或重写,避免 text/plain 响应里混入 HTML/JS 被错误执行 -
配合 X-Content-Type-Options 使用:只要加了
add_header X-Content-Type-Options "nosniff",浏览器就会严格按这个头声明的 Content-Type 解析内容,不再嗅探——这正是它存在的意义 -
对 script/style 类型做强制校验:例如用
if ($upstream_http_content_type ~* "^(text/css|application/javascript|text/javascript)$") { ... }触发额外日志或拦截逻辑(注意:if 在 location 外不推荐,可用 map + error_page 替代)
正确配置 X-Content-Type-Options 的方式
直接、静态、无条件地添加即可,无需 map 参与:
location / {
add_header X-Content-Type-Options "nosniff" always;
# 其他 proxy 或 static 配置
}
-
always参数确保即使响应状态码为 3xx/4xx/5xx 也生效 - 放在
http、server或location块均可,推荐统一在 server 级设置 - 不要尝试用 map 生成值,也不要基于 $http_accept 或 $request_uri 条件化开关——这既无标准依据,也无实际安全收益
若真需“按请求特征调整响应头”,可考虑的替代方案
虽然 X-Content-Type-Options 不支持动态,但其他头可以:
- 用
map $http_user_agent $security_policy { ... }控制X-Frame-Options或Content-Security-Policy的宽松度 - 用
map $upstream_http_content_type $content_disposition { ... }对下载类响应添加Content-Disposition: attachment - 用
map配合add_header设置自定义调试头(如X-Debug-ContentType),辅助排查 Content-Type 错误










