大多数网站仍然忽略的安全头:来自49真实审计的数据
响应头是随任何部署一起发送的单行配置。在我们审计的站点中,大多数都没有发送它们——Permissions-Policy 在 69% 上缺失,列表中最常采用的头仍在 41% 上缺失。
在本报告中,我们从每个受审站点重定向后的最终主页响应中读取 6 个安全头。 仅在预重定向跳转上发送的头不计入,因为浏览器从不会把它应用到页面上。 这个问题故意狭窄:响应是否携带该头。
在 49 站点中,审计时间为 5 月 23 至 August 31, 2026,答案通常是否定的。 Permissions-Policy 在其中 69% 缺失,Referrer-Policy 在 65% 缺失,Content-Security-Policy 在 61% 缺失,X-Frame-Options 在 51% 缺失,X-Content-Type-Options 在 43% 缺失,Strict-Transport-Security——最常采用的 6——在 41% 缺失。
方法论:每个域名的最新完成审计快照来自我们当前的检查集,约为 5 月 23 – August 31, 2026,49 个不同域名,已匿名化。 每个百分比是主页响应未携带该头的站点份额。 样本为自选——已运行审计的所有者——倾向于小型和中型站点,可能低估了整个网络的头采用率,因为大型平台在边缘设置这些头。 将份额视为长尾的方向性指标。
这些数字统计的是存在,而非质量
对测量的精确度在此很重要,因为它决定了这些数字能声称的上限。
这些数字描述每个站点的 1 个响应:重定向后的主页。 存在意味着非空值,仅此而已。 max-age 为 1 秒的 Strict-Transport-Security 头也算存在,宽松到允许任何内容的 Content-Security-Policy 同样如此。 存在并不说明策略是否构造良好。
这看起来像一个弱指标,直到你考虑它测量的内容。 任何值的头都是人类曾经打开服务器配置、CDN 规则或中间件文件并输入指令的证据。 这项测量检验的是站点配置层是否曾被有意触碰——这就是失败率为何有趣,而非通过率。
有两个细节决定你已发布的头部是否真正起到保护作用:
- Report-only CSP 不执行任何拦截。
Content-Security-Policy-Report-Only只记录违规而不阻止它们。 这是正确的起步方式,但在执行模式的Content-Security-Policy头部上线之前,该策略不提供任何保护。 frame-ancestors和 X-Frame-Options 面向不同的客户端。 CSP 的frame-ancestors指令是更好的控制方式,而旧客户端只读取旧版X-Frame-Options头部。 两者都要发布。
采用情况跟踪的是头部的年龄,而非其难度
失败率的排序接近逆时间顺序。HSTS 是 6 个中最旧的,并可在每个主要 CDN 仪表盘中切换,是采用率最高的。 X-Content-Type-Options 和 X-Frame-Options,都是在正式后继者出现之前就已存在的供应商约定,位于中间位置。 Referrer-Policy 和 Permissions-Policy,两个最新的,是缺失率最高的——而 Permissions-Policy,常见主机不会为你设置,排在最后。
它们在工程层面上没有一个比其他更难。 6 个中的 5 个只需在服务器块、CDN 规则或边缘中间件文件中添加一行静态代码,无需应用更改,也无行为风险。 区别在于它们已有多长时间来累积默认值,以及有多少博客文章、检查清单和框架模板已吸收它们。 我们在 对所有失败检查进行排名 时也看到相同的模式:响应头占据列表顶部,位于规范化、渲染和性能之上。 那个排名覆盖了不同窗口、不同样本和更早的检查集,因此两组百分比并非趋势线——但两者顶部头部的位置是持久发现。
另一个结构性原因是不可见性。 缺失头部在屏幕上不产生任何变化。 CMS 不会警告你,构建不会失败,仪表盘也不会变红。 缺失仅对检查原始响应的东西可见——这正是审计、浏览器安全状态以及越来越多的自动化阅读器所做的。 这与我们在 渲染一致性 中发现的相同不对称性相同:人类在浏览器中看到的与机器通过 HTTP 接收的内容悄然分离。
每个头部的保护作用
Strict-Transport-Security 告诉浏览器在指定期间拒绝对你域的明文 HTTP,从而关闭攻击者在网络上可劫持的重定向窗口,直至你的 http:// → https:// 重定向触发。 它也是列表中唯一带有承诺的头部:浏览器会遵守 max-age,即使你随后破坏 HTTPS。先简短,确认每个子域和资源都能通过 TLS 干净地提供,然后再扩展。
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy 限制脚本、样式、框架和连接的来源。 它是这里唯一包含事件而非预防某类事件的头部:当标签管理器被入侵或用户输入到达 DOM 时,CSP 决定注入的脚本是否能执行或到达它选择的服务器。 它也是唯一能破坏正常页面的头部,这就是为什么它放在下面序列的末尾。
Content-Security-Policy-Report-Only: default-src 'self'
X-Frame-Options 声明其他来源是否可以将你的页面放入框架。 没有它,你的界面可能会被嵌入到攻击者页面的透明覆盖层下,并被认为在你的网站上点击。 现代 CSP 用 frame-ancestors 更好地表达这一点;同时发布两者,因为旧客户端只读取旧头部。
X-Frame-Options: DENY
X-Content-Type-Options 阻止浏览器在声明的 Content-Type 看起来错误时猜测响应类型。 通过嗅探,上传的文件被当作文本提供时可能会被执行为脚本。 该头部恰好有 1 个有效值。
X-Content-Type-Options: nosniff
Referrer-Policy 管理当前 URL 的多少在外部点击和子资源加载时传递给第三方。 你的 URL 带有活动参数、内部搜索查询、账户标识符,有时还有令牌,页面上的每个分析像素和字体 CDN 都是接收者。 主流浏览器已趋向合理默认值,但默认值是用户代理为你做出的决定,且因客户端而异;发送该头部可让你明确策略,并让处理敏感 URL 的站点选择更严格的,例如 same-origin。
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy 决定你的文档及其嵌入框架可以请求哪些浏览器功能——摄像头、麦克风、地理位置以及其他强大功能列表。 缺少该头部时,你未禁用的所有功能都对页面上的每个脚本可用,包括你未编写的第三方标签。 拒绝你不使用的功能。
Permissions-Policy: camera=(), microphone=(), geolocation=()
先发布 4 的单行指令,然后花一个下午处理 CSP
保护价值和部署风险在确切的 1 头部上存在分歧,修复顺序将分歧倾向于发布。
Diagram source
graph TD
A[阅读你自己的响应头] --> B[部署 1:HSTS,短 max-age]
B --> C[部署 2:nosniff、Referrer-Policy、Permissions-Policy、X-Frame-Options]
C --> D[在 TLS 在所有地方得到确认后扩展 HSTS max-age]
D --> E[CSP 在报告模式下]
E --> F{违规报告干净?}
F -->|否| G[调整来源,保持报告模式]
G --> F
F -->|是| H[强制 CSP,添加 frame-ancestors]部署 1 — HSTS,简短。 保护价值高,且当你的网站已在 HTTPS 上提供服务时风险几乎为零。 先设置一个适度的 max-age,以便在被遗忘的子域出现 TLS 问题时仍可恢复。
部署 2 — 将 4 条静态行一起。 nosniff, Referrer-Policy, Permissions-Policy 以及 X-Frame-Options 是静态值,没有应用程序依赖。 它们是 6 个头部中的 4 个,并且在这些失败率下,平均网站缺失的大部分内容。 没有理由单独分阶段。
然后扩展 HSTS, 一旦你确认域下的每个主机都能通过 TLS 干净地提供服务。
最后 — CSP,在报告模式下。 部署 Content-Security-Policy-Report-Only,收集真实流量的违规,并枚举你实际依赖的脚本和连接来源。 只有在此之后才将头部切换为强制,并在你的 X-Frame-Options 行旁添加 frame-ancestors。 最高努力,序列中的最后一步,因为它是列表中唯一能让工作页面崩溃的项目。
在 1 命令中读取你自己的头部
整个测量可在终端中重现。跟随重定向,因为最终响应才是浏览器所应用的那个:
curl -sSL -o /dev/null -D - https://example.com/ \| grep -iE 'strict-transport-security|content-security-policy|x-frame-options|x-content-type-options|referrer-policy|permissions-policy'
每一行未返回即是你的主页未发送的头部。 所有 6 返回意味着存在栏已清除,接下来的问题——政策本身是否有用——值得提出。 付费的 SEOReport 诊断 会列出每个缺失头部及其解决值。
该数据集中的头部并非因难以获取或有争议而缺失。 它们缺失是因为网站日常运作中从未出现其缺失:没有错误、没有视觉变化、没有构建失败。 通过的站点是那些曾有人去寻找的——而那一次部署仍对大多数未找到的用户可用。