静态服务器可能返回正确的字节,却带上错误的 Content-Type。某个浏览器里页面看起来或许还正常,但下载、样式表、订阅阅读器或安全策略会把同一响应理解成别的东西。公开响应头才是契约;文件名只是服务器配置的输入。

CSS 路径之后检查公开响应的状态、实际字节和 Content-Type。正确 CSS 与 HTML 错误页分列。浏览器脚本和样式目标使用 nosniff,失败时应修复响应;CDN 或代理的公开响应头需要单独核对。
后缀不能证明实际收到的内容。应同时检查公开响应的状态、字节与媒体类型;CSS 路径上的 HTML 错误页不能用来测试 MIME 映射。nosniff 让脚本和样式目标上的类型不匹配以可见方式失败。

检查有代表性的格式

检查一份 HTML 文档、样式表、SVG、feed 与可下载脚本。包含响应头但丢弃正文:

for path in / /assets/site.css /favicon.svg /index.xml /downloads/check-http-headers.sh; do
  curl -sS -D - -o /dev/null "https://www.example.test$path" \
    | awk -v path="$path" '
        BEGIN { print "== " path }
        /^HTTP\// || tolower($1) == "content-type:" || tolower($1) == "x-content-type-options:" { print }
      '
done

把示例资源路径换成当前发布中确实存在的文件;虚构 CSS 路径返回 HTML 404,并不能测试 MIME 映射。期望的媒体类型因资源而异,但应该具体且稳定。HTML 通常应包含字符集。CSS 与 SVG 不应被当作泛型二进制数据提供服务。用于下载的 shell 脚本不应被声明为 HTML。

该循环只是展示响应头,不会自动断言成功、检视被丢弃的字节,也不会执行浏览器的阻止逻辑。应将资源与发布制品核对,并在浏览器中检查它作为样式表或脚本的实际加载结果。把相同 URL 直接当作文档打开,测试的是另一种请求目标。

保持 nosniff 一致

X-Content-Type-Options: nosniff 请求支持它的浏览器在脚本与样式目标上尊重声明的类型,而不是猜测。在这项 Fetch 检查中,脚本类目标需要 JavaScript MIME 类型,样式目标需要 text/css;类型缺失或无法使用也会失败。这样,不匹配会变成可见的失败,而不是因浏览器而异的解读。

该响应头不能修复错误类型,也不能让任意内容变安全。部署时核对资源清单;若脚本或样式被拒绝,应修复响应,而不是移除保护:

X-Content-Type-Options: nosniff

检查服务器映射

静态服务器通常根据扩展名推导类型。如果某个新扩展名被当作 application/octet-stream 提供服务,先判断这是否有意为之,再决定是否加入全局覆盖。一个窄映射比一条会改变所有响应的规则更容易复核。

在公开主机名上重复这些检查。CDN 或反向代理可能替换掉正确的源站响应头;而一个友好的错误页可能为后缀像 CSS 或 JavaScript 的路径返回 HTML。

来源