Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

README.md

CVE-2026-93538 — Cross-tenant BundleDeployment/Secret disclosure via spoofed agent cluster labels

  • Advisory: GHSA-h9p5-fp5h-qpqr · CVE-2026-93538
  • Severity: High (CVSS 4.0 7.1 — AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:L/VA:N/SC:H/SI:L/SA:N) · CWE-290 / CWE-639 / CWE-863
  • Affected: Fleet >=v0.12.0 <v0.12.19, >=v0.13.0 <v0.13.15, >=v0.14.0 <v0.14.10, >=v0.15.0 <v0.15.6, >=v0.16.0 <v0.16.1
  • Patched: Fleet v0.16.1, v0.15.6, v0.14.10, v0.13.15, v0.12.19 · Rancher v2.15.1, v2.14.5, v2.13.9, v2.12.13, v2.11.17
  • Status: publicly disclosed and fixed. Reported by Pig-Tail through coordinated disclosure.

Summary

During agent-initiated cluster registration the registering agent fully controls ClusterRegistration.Spec.ClusterLabels, and the controller copied every key verbatim onto the upstream Cluster object with no key allowlist:

// internal/cmd/controller/agentmanagement/controllers/clusterregistration/controller.go
if !config.Get().IgnoreClusterRegistrationLabels {
    maps.Copy(labels, request.Spec.ClusterLabels)   // arbitrary keys, incl. management.cattle.io/*
}

Fleet resolves GitRepo and Bundle targets from exactly those labels, so a party able to register a cluster into a shared workspace namespace can make its own cluster satisfy targeting rules an administrator wrote for someone else's cluster.

Why name-based targeting is spoofable too

clusterSelector / clusterGroupSelector matching on attacker-set label values would be a hardening issue on its own. What makes this an authorization gap is that clusterName targeting is spoofable as well: the name criterion falls back to the value of the management.cattle.io/cluster-display-name label, which is copied straight from the agent-supplied ClusterLabels. An agent that registers with

management.cattle.io/cluster-display-name: "victim-prod-cluster"

satisfies a target the administrator believes selects one specific cluster by name — a reserved, management-plane-owned key being self-asserted by the registering party.

Exploit path

  1. Learn or guess the victim target selector — low-entropy operational labels (env: prod) or the victim cluster display name, which is visible in the Rancher UI.
  2. Register a cluster into the shared workspace namespace with crafted ClusterLabels.
  3. On the next Bundle/GitRepo reconcile the attacker's cluster matches the victim's target.
  4. Fleet creates the BundleDeployment and the resolved options/values Secret in the matched cluster's own status.namespace, where the attacker's agent is entitled to read them.

Impact

Cross-tenant disclosure of another tenant's bundle manifests and of resolved Helm values, including values sourced through valuesFrom Secrets, plus deployment of that tenant's intended workload onto a cluster they do not control. The victim's own deployment is not modified or removed.

Preconditions (why this is CONDITIONAL)

  • The deployment must use agent-initiated registration — Fleet copies agent-supplied labels only when it creates the Cluster object as part of that flow.
  • Standalone Rancher in its default configuration is not affected: Rancher uses manager-initiated registration and creates the Fleet Cluster object in advance.
  • Multiple trust domains must share one Fleet registration namespace (several tenants registering into fleet-default), with the affected Bundle/GitRepo targeting by label or by cluster name.
  • IgnoreClusterRegistrationLabels left at its default false.

Adversarial re-read

  • "Cluster labels are documented as agent-controlled, and IgnoreClusterRegistrationLabels exists." — True for ordinary labels. The reportable gap is the reserved management.cattle.io/ namespace being self-assertable, which defeats name-based targeting that administrators reasonably assume is not agent-controlled.
  • "Same namespace means same tenant." — Only under one-workspace-per-tenant. The multi-tenant deployments in scope share a registration namespace, which is why the finding is conditional.
  • Not a duplicate of GHSA-xr65 (controller-side valuesFrom reads) or GHSA-864g (PSS bypass via addLabelsFromOptions): here the attacker abuses cluster labels to attract targeting and receives the deployment in its own namespace.

Fix

Fleet now discards reserved label keys supplied by an agent during agent-initiated registration, so labels in the management.cattle.io/ namespace — including the cluster display name label used for name-based targeting — can no longer be self-asserted. Such labels are honoured only when set by the management plane after registration. Environments that intentionally relied on an agent setting a reserved label at install time must apply it to the Cluster object from the management plane instead.

Write-up only. No standalone runnable PoC is published for this finding here: confirming it end to end requires a two-cluster registration setup. The chain is verifiable statically at the cited call sites. Refer to the linked advisory for the vendor's own account and fixed releases.