Helmet 响应头完整速查

本章以当前 Helmet 官方行为为依据讲解主要 Header。Helmet 会随版本调整默认值,因此升级依赖时应同时查看官方文档和真实响应,不能只依赖教程中的静态清单。

可以用下面的命令确认当前项目实际返回的 Header:

curl -i http://127.0.0.1:8080/health

1. 默认策略总览

调用 app.use(helmet()) 时,常见默认行为如下:

Header/行为 常见默认状态 主要作用
Content-Security-Policy 开启 限制页面资源和脚本执行
Cross-Origin-Opener-Policy 开启 隔离跨源浏览上下文
Cross-Origin-Resource-Policy 开启 限制其他源使用响应资源
Origin-Agent-Cluster 开启 请求按 Origin 隔离代理集群
Referrer-Policy 开启 控制 Referer 信息
Strict-Transport-Security 开启 要求后续使用 HTTPS
X-Content-Type-Options 开启 禁止 MIME 嗅探
X-DNS-Prefetch-Control 开启 控制 DNS 预取
X-Download-Options 开启 限制旧版 IE 下载文件直接打开
X-Frame-Options 开启 限制页面被 iframe 嵌入
X-Permitted-Cross-Domain-Policies 开启 限制旧插件跨域策略
X-Powered-By 移除 不暴露 Express 标识
X-XSS-Protection 设置为 0 关闭有历史问题的旧式 XSS 过滤器
Cross-Origin-Embedder-Policy 通常默认关闭 要求嵌入资源满足跨源隔离规则

“默认开启”不等于适合所有业务。下面逐项说明具体影响。

2. Content-Security-Policy(CSP)

示例:

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'self'

CSP 是 Helmet 中影响最广的一项。它通常附在 HTML 文档响应上,由浏览器约束该文档可以加载或执行什么。

高频 directive

Directive 控制对象 配错后的常见现象
default-src 未单独声明类型时的兜底来源 多种资源同时失败
script-src JavaScript 来源及执行方式 页面按钮失效、白屏
style-src CSS 和内联样式 页面失去样式
img-src 图片来源 CDN、data URL 图片失败
font-src 字体来源 图标或字体回退
connect-src fetch、XHR、WebSocket、EventSource API 请求在浏览器端被 CSP 阻止
object-src <object>、插件内容 嵌入内容失败,通常建议 'none'
frame-src 当前页面可以嵌入哪些 frame 第三方页面无法嵌入
frame-ancestors 谁可以 iframe 嵌入当前页面 外部系统嵌入失败
base-uri <base> 可使用的 URL 阻止恶意重写相对 URL 基准
form-action 表单可以提交到哪里 第三方表单提交失败
upgrade-insecure-requests 把 HTTP 子资源升级为 HTTPS 本地开发 URL 可能被升级

'self' 的含义

'self' 是当前文档的 Origin,不是“本公司所有域名”。页面在 https://www.example.com 时,'self' 不自动包含 https://api.example.com

例如页面需要连接 API:

Content-Security-Policy: default-src 'self'; connect-src 'self' https://api.example.com

CORS 即使允许了 www.example.com,若页面自己的 CSP connect-src 没有允许 API,fetch 仍会失败。这是 Helmet 与 CORS 看似“冲突”的典型来源。

JSON API 与 HTML 的差别

API 的 JSON 响应带 CSP,通常只约束该响应被当作文档打开时的行为,不会控制发起 fetch 的原页面。要保护 Nginx 返回的前端页面,应在 index.html 的响应上设置匹配前端构建产物的 CSP。

Report-Only

上线前可先观察违规而不直接阻断:

Content-Security-Policy-Report-Only: ...

Report-Only 适合收集真实资源来源并逐步收紧,但它本身不提供阻断保护,不能作为永久替代。

3. Cross-Origin-Opener-Policy(COOP)

常见值:

Cross-Origin-Opener-Policy: same-origin

COOP 控制顶级页面与通过 window.open() 打开的页面是否处于同一浏览上下文组。same-origin 可以降低跨源窗口侧信道风险,但可能让跨源窗口的 window.opener 关系被切断。

高风险兼容场景:

普通 JSON fetch 通常不会因为 COOP 失败。问题更多出现在 Express 直接返回 HTML 页面时。

4. Cross-Origin-Embedder-Policy(COEP)

可能的值:

Cross-Origin-Embedder-Policy: require-corp

COEP 要求页面嵌入的跨源资源明确通过 CORS 或 CORP 授权,是启用跨源隔离能力(例如部分 SharedArrayBuffer 场景)的一环。Helmet 通常不会默认启用它,因为它容易让第三方图片、脚本、字体和 iframe 突然失效。

只有在确实需要跨源隔离,并能控制所有资源响应头时再启用。COEP 是页面策略;纯 JSON API 是否受影响取决于它是否被该页面作为资源加载。

5. Cross-Origin-Resource-Policy(CORP)

常见默认值:

Cross-Origin-Resource-Policy: same-origin

CORP 是响应资源对使用方的声明:哪些源可以把它作为资源加载。

含义
same-origin 只允许同源使用
same-site 允许同站点使用
cross-origin 允许跨源使用

它和 CORS 不等价:CORS 主要控制跨源 JavaScript 读取响应;CORP 主要防止响应被不被允许的页面嵌入或加载。在跨域图片、文件预览、CDN 和启用 COEP 的页面中尤其要关注。

如果 API 只由同源路径 /api 调用,默认通常影响不大;若 api.example.com 返回图片给 www.example.com 显示,则应进行真实浏览器测试,并按资源用途选择 CORP/CORS,而不是直接全局放宽。

6. Origin-Agent-Cluster

常见值:

Origin-Agent-Cluster: ?1

它请求浏览器按 Origin 而不是更宽泛的 Site 来隔离代理集群,减少不同 Origin 共享某些执行环境的机会。普通业务通常感知不到,也很少需要单独修改。

它不是服务器 Cluster,也不是 Node.js cluster 模块;这里的 Agent Cluster 是浏览器内部概念。

7. Referrer-Policy

常见默认值:

Referrer-Policy: no-referrer

它控制浏览器访问下一资源时发送多少来源 URL 信息。策略越严格,隐私越好,但依赖 Referer 的统计、反盗链或业务跳转可能缺少数据。

常见策略:

注意规范中的请求头拼写历史上是 Referer,而策略响应头是 Referrer-Policy

8. Strict-Transport-Security(HSTS)

常见形式:

Strict-Transport-Security: max-age=31536000; includeSubDomains

浏览器通过 HTTPS 收到该 Header 后,会在 max-age 时间内自动把该主机的 HTTP 访问升级为 HTTPS。它能降低降级攻击和用户误用 HTTP 的风险。

上线风险:

不要在 HTTPS、证书和所有相关子域名尚未准备好时盲目启用长期 HSTS,更不要轻率加入预加载列表。

9. X-Content-Type-Options

固定形式:

X-Content-Type-Options: nosniff

浏览器不应把声明为一种 MIME 的内容猜成另一种可执行类型。它提升安全性的同时会暴露服务器配置错误:

遇到问题应修正 Content-Type,而不是优先关闭 nosniff

10. X-Frame-Options

常见默认值:

X-Frame-Options: SAMEORIGIN

它用于降低点击劫持风险。更现代、更灵活的替代是 CSP frame-ancestors,可以声明多个允许来源。为了兼容旧浏览器,项目可能同时设置两者,但策略应保持一致。

API JSON 通常不会被正常 iframe 使用,因此影响有限;Express 若提供 Swagger、报表或 HTML 预览,则要确认是否有合法嵌入需求。

11. X-DNS-Prefetch-Control

常见形式:

X-DNS-Prefetch-Control: off

它控制浏览器是否预先解析页面中链接的域名。关闭可减少一些隐私泄漏和非必要网络行为,但也可能失去少量性能优化。它主要影响 HTML 页面,不是 API fetch 的核心安全项。

12. X-Download-Options

常见形式:

X-Download-Options: noopen

它主要针对旧版 Internet Explorer,降低用户直接在网站上下文中打开下载文件的风险。现代浏览器中的影响很有限,不能代替安全的 Content-Disposition、文件类型验证和病毒扫描。

13. X-Permitted-Cross-Domain-Policies

常见形式:

X-Permitted-Cross-Domain-Policies: none

它限制 Adobe Flash、Acrobat 等旧式客户端读取跨域策略文件。现代 Web 应用中存在感较低,但作为防御性默认项成本也较低。

14. X-Powered-By

Express 默认可能返回:

X-Powered-By: Express

Helmet 会移除它,减少不必要的技术栈暴露。但隐藏名称不能阻止攻击者识别技术栈,更不能替代升级依赖和修复漏洞。

也可以直接使用:

app.disable("x-powered-by");

15. X-XSS-Protection

Helmet 会将其设置为:

X-XSS-Protection: 0

这是有意关闭旧浏览器内置、曾产生安全副作用的 XSS Auditor,而不是“关闭应用的 XSS 防护”。现代防线应依靠正确转义、CSP 和安全编码。

16. 不要重复设置相互矛盾的值

当 Nginx 和 Express 都添加安全头时,可能出现重复 Header 或外层覆盖内层的情况。浏览器对不同 Header 的重复值处理并不完全一致,不应依靠猜测。

建议: