🎯 CVE-2026-41050 深度技术分析:漏洞根因 · PoC/EXP · 检测指纹

🎯 CVE 全聚合深度分析

CVE-2026-41050 深度技术分析

📊 聚合 2 来源🕵️ 含指纹
NVD-LatestGitHub-Advisory

CVE-2026-41050 Fleet Helm Deployer 服务账户模拟绕过漏洞深度分析

摘要:CVE-2026-41050 是 Rancher Fleet 组件中一个严重的服务账户(ServiceAccount)模拟绕过漏洞,CVSS 评分为 9.9。由于 Fleet 的 Helm deployer 在两条代码路径上没有完全应用服务账户模拟,导致拥有 Fleet 监控仓库 git push 权限的租户可以读取每个下游集群任意命名空间中的 Secret。漏洞利用无需集群凭据,仅需向 Fleet 托管的 Git 仓库提交恶意 chart 或修改 fleet.yaml,即可在 Helm 模板渲染阶段或 values 加载阶段触发越权读取。

📌 漏洞概述

CVE 编号:CVE-2026-41050
CVSS 评分:9.9(Critical)
GitHub Advisory:GHSA-765j-qfrp-hm3j(CRITICAL)
受影响产品:Rancher Fleet(go/github.com/rancher/fleet)
漏洞类型:CWE-284 不正确的访问控制(服务账户模拟绕过)
CISA KEV:未收录(暂无已利用漏洞列表)
公开 PoC/EXP:暂无

Fleet 是 Rancher 生态中用于 GitOps 持续交付的组件,能够将 Git 仓库中的 Helm chart 部署到多个下游集群。在多租户场景中,Fleet 通过 ServiceAccount impersonation 限制每个租户(Tenant)在下游 Kubernetes 集群中的操作权限,使租户只能使用授权给其服务账户的 RBAC 权限。该机制是 Fleet 多租户隔离边界的关键。CVE-2026-41050 则表明这一边界在 Helm deployer 内部并未被完全执行,逃逸到两条辅助代码路径上,形成高严重性越权读取漏洞。

🔬 漏洞根因分析

Fleet 的 Helm deployer 在安装或升级 Helm Release 时,会为每个 GitRepo 创建对应的 Helm Action,同时使用 WithImpersonationConfig 设置要模拟的服务账户,以控制 Helm 在集群内执行 API 操作的权限。但问题在于,Helm 的某些操作并不是发生在同一个 action 上下文中,而是存在独立调用链。

漏洞根因具体体现在两条路径:

路径一:Helm lookup 函数绕过
Helm chart 模板引擎提供内置的 lookup 函数,模板可借此在渲染时查询 Kubernetes 资源。该函数需要调用 Kubernetes API。在存在漏洞的实现中,Helm 模板引擎使用的客户端并非经过 WithImpersonationConfig 配置的客户端,而是直接复用了 fleet-agent 自身的高权限 kubeconfig 凭证(通常是 cluster-admin)。于是,chart 模板中只需要写 {{ lookup "v1" "Secret" "kube-system" "some-token" }},就能以 fleet-agent 的身份读取任何命名空间的 Secret,完全绕过了租户 RBAC 的限制。

路径二:fleet.yamlhelm.valuesFrom 绕过
Fleet 允许用户通过 fleet.yamlhelm.valuesFrom 引用 Secret 或 ConfigMap,并将其内容作为 Helm values 注入。在实现中,这个引用解析过程使用了一个独立的 Kubernetes 客户端,该客户端同样没有继承模拟身份,而是以 fleet-agent 的 cluster-admin 身份运行。攻击者可以将 valuesFrom 指向任意命名空间中的 Secret,例如:

helm:
  valuesFrom:
  - secretRef:
      name: target-secret
      namespace: kube-system

valuesFrom 的读取逻辑没有使用模拟后的服务账户,导致跨命名空间读取成功。

从设计角度看,Fleet 将“主部署流程”与“辅助数据获取流程”分离,但未能将 impersonation 上下文贯穿到所有客户端实例中,形成了不一致的授权状态。这是典型的“安全配置未全面覆盖代码路径”设计缺陷。Semgrep 检测规则中也明确匹配 helm.ActionConfiguration(...) 后是否调用 WithImpersonationConfig(...),用于发现那些遗漏模拟配置的 Helm Action 构造点。

💥 影响与危害

利用该漏洞的租户必须拥有 Fleet 监控仓库的 git push 权限。这只要求攻击者可以修改 Git 仓库内容,而无需任何下游集群的 kubeconfig 或 RBAC 权限。当存在漏洞的 Fleet-agent 开始部署或同步该 GitRepo 时,攻击者构造的恶意 chart 会被渲染并下发到该 GitRepo 指向的所有下游集群。影响范围包括:

  • 跨命名空间读取全部 Secret:fleet-agent 以 cluster-admin 身份运行,因此攻击者实质上可以读取下游集群中全部命名空间的所有 Secret,包括 Kubelet 凭据、ServiceAccount Token、TLS 私钥、云厂商凭据以及连接外部服务的数据库密码、API Key 等。
  • 横向扩散至外部系统:Secret 中可能包含用于外部服务的凭据,例如对象存储、CI/CD 系统、云 API 或消息队列。攻击者获取后可登录这些外部系统,造成数据泄漏或进一步破坏。
  • 多集群全网沦陷:如果多个下游集群由同一个 Fleet 实例管理,攻击者的恶意仓库一旦被同步,可在所有目标集群上读取 Secret,影响面广。
  • 潜在供应链风险:Fleet 的典型用途是 Kubernetes 应用交付。攻击者可能在 chart 中嵌入恶意逻辑,不仅读取 Secret,还可能利用读取到的数据操纵业务应用。

由于泄露的凭据可能属于第三方服务,漏洞的最终影响是非确定性的:从仅影响 Kubernetes 集群内部的机密信息,到导致外部云账号被接管、数据被删除或业务被勒索,完全取决于泄露凭据的权限范围。

🧪 PoC 复现分析

目前没有公开的 PoC 仓库或代码。但从漏洞描述和修复建议可以推断出可行的复现原理与关键步骤。一个最小化 PoC 需要两个核心组件:

组件一:恶意 Helm Chart
攻击者在 GitRepo 中放置一个 Helm chart,其模板包含类似以下内容:

{{- $secret := lookup "v1" "Secret" "kube-system" "my-target-secret" -}}
{{- if $secret -}}
{{ printf "%s" (index $secret.data "token") | b64dec }}
{{- end -}}

这段模板在 Helm 渲染时调用 lookup,以漏洞代码路径中的高权限客户端查询任意命名空间的 Secret,并将结果输出到生成的 Kubernetes 资源中(例如 ConfigMap 或日志)。如果模板引擎未使用 impersonation,该查询将成功返回。

组件二:恶意 fleet.yaml
攻击者还可以修改 fleet.yaml,使用 helm.valuesFrom 引用目标 Secret:

helm:
  valuesFrom:
  - secretRef:
      name: target-secret
      namespace: default
  - configMapRef:
      name: app-config
      namespace: kube-system

当 Fleet 解析这些引用时,如果解析过程使用了未模拟的 client,则会把目标 Secret/ConfigMap 中的 key-value 作为 Helm values 传入。攻击者随后可在模板中通过 .Values.target-secret 将其打印到可观察的资源字段中,或者通过 HTTP 请求外传。

利用过程非常简单:攻击者提交恶意内容到仓库,Fleet-agent 自动同步并渲染。不需要提前拿到 Kubernetes 集群任何权限,仅凭借 git push 这一动作即可触发越权读取。

⚔️ EXP 利用分析

由于没有公开的 EXP 代码,这里的“利用分析”基于漏洞机制推演完整的攻击链路。一种典型的利用链如下:

  1. 获取 git push 权限:攻击者通过合法途径(本身是仓库贡献者)或社会工程获得 Fleet 所监控 Git 仓库的写权限。
  2. 构造恶意 GitRepo 内容:创建或修改 Helm chart 的 templates/ 文件,利用 lookup 函数读取目标 Secret;或在 fleet.yaml 中利用 valuesFrom 读取指定 Secret/ConfigMap。
  3. 触发 Fleet 同步:Fleet-agent 通常会周期性同步或基于 webhook 实时监听 Git 仓库。攻击者 push 代码后,Fleet-agent 会立即开始部署。
  4. 数据外泄:恶意模板将读取到的 Secret 写入到创建的 Kubernetes 资源中(如 ConfigMap、Secret、Job 环境变量),或者通过 Helm 的 post-renderer、钩子、pod 中运行的命令将内容发送到攻击者控制的服务器。由于 agent 的 cluster-admin 权限,该请求不会受到目标集群 RBAC 阻挡。
  5. 后渗透:攻击者获得读取到的云凭据或集群令牌后,可以访问云控制台、其他服务,或直接获取新集群的 RBAC 管理员权限。

值得注意的是,这种利用可能比传统集群逃逸更隐蔽,因为它完全发生在正常的 GitOps 流水线中。安全团队很难从 Kubernetes API server 的审计日志中区分合法的 chart 渲染和恶意的 lookup 调用,尤其是在高权限 agent 的访问模式下。

🕵️ 检测指纹说明

现有检测指纹为一组 Semgrep 规则,用于扫描 Go 源代码中的漏洞模式。规则提供了两个核心检测场景:

  • 规则 CVE-2026-41050-rce-go:检测代码中是否创建了 helm.ActionConfiguration(...) 对象且没有随后的 WithImpersonationConfig(...) 调用。如果匹配,则说明 Helm 操作可能缺少服务账户模拟,存在权限绕过风险。该规则标记 severity 为 ERROR,并提示使用 action.WithImpersonationConfig(impersonateConfig) 进行修复。
  • 规则 CVE-2026-41050-rce-go-lookup:专门检测 Helm 模板引擎的 lookup 路径上是否缺少模拟配置。该规则在源码层面定位到 Helm 客户端初始化位置,防止开发者遗漏对 lookup 路径的处理。

这些规则同时引用了 GHSA-765j-qfrp-hm3j 和 NVD 的 CVE 详情,可用于 CI/CD 流水线,在构建或合并前扫描 fleet 及其衍生项目源码。部署方式为在项目根目录添加 Semgrep 或将规则集成到 Semgrep AppSec 平台中。规则中的 OWASP 映射为 A1: Injection(语义上应当理解为外部控制数据注入到高权限操作中)。对于安全运维人员,也可以在不运行完整代理的情况下,用相同规则对本地仓库进行快速白盒审计。

需要注意的是,Semgrep 规则只覆盖 Go 代码中的静态调用模式,无法检测内部动态拼装客户端的方式。如果攻击者或开发人员通过变量间接传递 action 配置,规则可能会漏报。因此还应配合运行时审计,例如检查 Fleet-agent 的 Helm 渲染日志、Kubernetes API Server 的 impersonation 审计日志,以及 Secret 资源的访问记录。

🛡️ 修复与缓解

官方修复:Rancher 官方安全通告(GHSA-765j-qfrp-hm3j)已提供修复版本。受影响用户应优先升级到包含修复的 Fleet 版本。修复的核心方案是确保所有与 Helm 相关的 Kubernetes API 访问路径都使用模拟后的服务账户,即在每个 helm.ActionConfiguration 上都调用:

action.WithImpersonationConfig(impersonateConfig)

特别是 Helm lookup 函数和 valuesFrom 解析过程,必须使用继承自租户 ServiceAccount 的客户端,而不是 fleet-agent 的本地 kubeconfig 客户端。

缓解措施:

  • 最小化 git push 权限:严格管理 Fleet 所监控仓库的写权限,仅授予完全可信的租户和运维人员。
  • 在不可信环境中避免多租户共用 Fleet:如果所有用户均受信任,单租户部署不受该漏洞影响;多租户部署应尽快升级。
  • 审计潜在泄露凭据:根据官方建议,检查集群中可能被读取的 Secret、ConfigMap,尤其是来自外部服务的凭据。如果发现异常访问记录或无法确定是否受影响,应轮换相关凭据。
  • 启用 Kubernetes 审计日志:重点关注 fleet-agent 对 Secret/ConfigMap 的 get/list 操作,以及 impersonation 用户与 fleet-agent 自身用户之间的访问差异。
  • 限制 Fleet-agent 的权限:如果可能,将 Fleet-agent 自身权限从 cluster-admin 降低为“仅部署所需的最小权限”,这样即使模拟被绕过,单个租户也只能读取 agent 具有权限的资源,但由于该漏洞目标是读取所有命名空间 Secret,最小权限法可以有效收敛影响。
  • 使用网络策略与出口控制:防止恶意模板将数据外传到互联网,降低数据泄露影响。

综上,CVE-2026-41050 是一个非常典型的 GitOps 多租户隔离失效漏洞。攻击面简单、利用代价低、影响范围大。所有使用 Fleet 进行多集群应用交付的组织都应对该漏洞给予最高优先级处理,立即升级到修复版本,并完成凭据审计。

🕵️ 检测指纹规则

🛡️ Semgrep 审计规则: CVE-2026-41050.yaml

rules:
  - id: CVE-2026-41050-rce-go
    languages:
      - go
    severity: ERROR
    message: "Potential Helm impersonation bypass due to missing ServiceAccount impersonation in Helm deployer. Fleet-agent may use cluster-admin credentials instead of impersonated ServiceAccount,
allowing privilege escalation."
    patterns:
      - pattern: helm.ActionConfiguration(...)
      - pattern-not: helm.ActionConfiguration(...).WithImpersonationConfig(...)
    fix: "Ensure Helm action uses impersonated ServiceAccount credentials: action.WithImpersonationConfig(impersonateConfig)"
    metadata:
      cwe: "CWE-284"
      owasp: "A1: Injection"
      technology: fleet
      references:
        - "https://github.com/rancher/fleet/security/advisories/GHSA-765j-qfrp-hm3j"
        - "https://nvd.nist.gov/vuln/detail/CVE-2026-41050"
  - id: CVE-2026-41050-rce-go-lookup
    languages:
      - go
    severity: ERROR
    message: "Potential Helm lookup bypass: missing impersonation on Helm template engine queries. Use cluster-admin credentials instead of impersonated ServiceAccount."
    patterns:
      - pattern: $CLIENT.Get(...)
      - pattern-not: $CLIENT.WithImpersonation(...).Get(...)
    fix: "Client should use impersonation: impersonatedClient.Get(...)"
    metadata:
      cwe: "CWE-284"
      owasp: "A1: Injection"
      technology: fleet
      references:
        - "https://github.com/rancher/fleet/security/advisories/GHSA-765j-qfrp-hm3j"
        - "https://nvd.nist.gov/vuln/detail/CVE-2026-41050"
  - id: CVE-2026-41050-rce-go-valuesfrom
    languages:
      - go
    severity: ERROR
    message: "Potential valuesFrom bypass: Fleet-agent reads Secret/ConfigMap references in fleet.yaml without proper impersonation,
using cluster-admin privileges."
    patterns:
      - pattern: $CLIENT.Get($NAMESPACE,$NAME,...)
      - pattern-not: $CLIENT.WithImpersonation($IMP).Get($NAMESPACE,$NAME,...)
    fix: "Use impersonated client: restClient.WithImpersonation(impConfig).Get(namespace,name,
opts)"
    metadata:
      cwe: "CWE-284"
      owasp: "A1: Injection"
      technology: fleet
      references:
        - "https://github.com/rancher/fleet/security/advisories/GHSA-765j-qfrp-hm3j"
        - "https://nvd.nist.gov/vuln/detail/CVE-2026-41050"

🛡️ CodeQL 审计规则: CVE-2026-41050.ql

/**
 * @kind path-problem
 * @id go/impersonation-bypass/cve-2026-41050
 * @name Fleet Helm impersonation bypass of RESTClientGetter retains cluster-admin credentials
 * @description User-controlled ServiceAccount impersonation is bypassed in Fleet's Helm deployer,
allowing tenant to read secrets outside RBAC scope via Helm lookup or valuesFrom
 * @problem.severity error
 * @tags security
 *       external/cwe/cwe-284
 */
import go
import semmle.go.security.ImpersonationQuery
import ImpersonationFlow::PathGraph

class HelmLookupSink extends DataFlow::Node {HelmLookupSink() {exists(MethodCall mc |mc.getTarget().hasQualifiedName("helm.sh/helm/v3/pkg/action",
"Configuration","getClient") and
      this = mc.getResult()
    )
  }}class ValuesFromSink extends DataFlow::Node {ValuesFromSink() {exists(FunctionCall fc |fc.getTarget().hasQualifiedName("github.com/rancher/fleet/pkg/helm","getValuesFrom") and
      this = fc.getAnArgument()
    )
  }}class ImpersonationConfig extends TaintTracking::Configuration {ImpersonationConfig() {
this = "ImpersonationConfig" }override predicate isSource(DataFlow::Node source) {exists(Parameter p |p.getFunction().hasQualifiedName("github.com/rancher/fleet/pkg/helm","deploy") and
      p.getName() = "impersonate" and
      source.asParameter() = p
    )
  }override predicate isSink(DataFlow::Node sink) {sink instanceof HelmLookupSink or
    sink instanceof ValuesFromSink
  }
override predicate isAdditionalTaintStep(DataFlow::Node node1,DataFlow::Node node2) {exists(FunctionCall fc |fc.getTarget().hasQualifiedName("github.com/rancher/fleet/pkg/helm","newClient") and
      fc.getAnArgument() = node1.asExpr() and
      node2.asExpr() = fc.getResult()
    )
  }}from ImpersonationFlow::PathNode source,
ImpersonationFlow::PathNode sink
where ImpersonationFlow::flowPath(source,sink)
select sink.getNode(),source,sink,"User-controlled impersonation subject flows to Helm operation without proper credential restriction"

🤖 本文由漏洞情报系统自动聚合生成 · 2026-08-01 03:07 · 数据源: NVD/GitHub-Advisory/OSV/CISA-KEV/Exploit-DB/PoC-in-GitHub + 检测规则库

[!] CONTACT_CHANNELS

如需商务合作、技术咨询或漏洞反馈,请通过以下离岸节点联系作者。

> PING_AUTHOR (@A1RedTeam)