GitHub Advisoryadvisory · Go

GHSA-9m94-w2vq-hcf9 KubeVirt VMI Denial-of-Service (DoS) Using Pod Impersonation

MEDIUM Published 2025-11-06 Modified 2025-11-17 Official page ↗
Aliases
CVE-2025-64435
Ecosystem
Go
Packages
kubevirt.io/kubevirt
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H
Weaknesses
CWE-703
Reviewed
2025-11-06

Affected packages

• Go kubevirt.io/kubevirt: < 1.7.0-beta.0 → fixed in 1.7.0-beta.0

Description

Summary _Short summary of the problem. Make the impact and severity as clear as possible. A logic flaw in the `virt-controller` allows an attacker to disrupt the control over a running VMI by creating a pod with the same labels as the legitimate `virt-launcher` pod associated with the VMI. This can mislead the `virt-controller` into associating the fake pod with the VMI, resulting in incorrect status updates and potentially causing a DoS (Denial-of-Service). Details _Give all details on the vulnerability. Pointing to the incriminated source code is very helpful for the maintainer._ A vulnerability has been identified in the logic responsible for reconciling the state of VMI. Specifically, it is possible to associate a malicious attacker-controlled pod with an existing VMI running within the same namespace as the pod, thereby replacing the legitimate `virt-launcher` pod associated with the VMI. The `virt-launcher` pod is critical for enforcing the isolation mechanisms applied to the QEMU process that runs the virtual machine. It also serves, along with `virt-handler`, as a management interface that allows cluster users, operators, or administrators to control the lifecycle of the VMI (e.g., starting, stopping, or migrating it). When `virt-controller` receives a notification about a change in a VMI's state, it attempts to identify the corresponding `virt-launcher` pod. This is necessary in several scenarios, including: • When hardware devices are requested to be hotplugged into the VMI—they must also be hotplugged into the associated `virt-launcher` pod. • When additional RAM is requested—this may require updating the `virt-launcher` pod's cgroups. • When additional CPU resources are added—this may also necessitate modifying the `virt-launcher` pod's cgroups. • When the VMI is scheduled to migrate to another node. The core issue lies in the implementation of the `GetControllerOf` function, which is responsible for determining the controller (i.e., owning resource) of a given pod. In its current form, this logic can be manipulated, allowing an attacker to substitute a rogue pod in place of the legitimate `virt-launcher`, thereby compromising the VMI's integrity and control mechanisms. ```go //pkg/controller/controller.go func CurrentVMIPod(vmi *v1.VirtualMachineInstance, podIndexer cache.Indexer) (*k8sv1.Pod, error) { // Get all pods from the VMI namespace which contain the label "kubevirt.io" objs, err := podIndexer.ByIndex(cache.NamespaceIndex, vmi.Namespace) if err != nil { return nil, err } pods := []*k8sv1.Pod{} for _, obj := range objs { pod := obj.(*k8sv1.Pod) pods = append(pods, pod) } var curPod *k8sv1.Pod = nil for _, pod := range pods { if !IsControlledBy(pod, vmi) { continue } if vmi.Status.NodeName != "" && vmi.Status.NodeName != pod.Spec.NodeName { // This pod isn't scheduled to the current node. // This can occur during the initial migration phases when // a new target node is being prepared for the VMI. continue } // take the most recently created pod if curPod == nil || curPod.CreationTimestamp.Before(&pod.CreationTimestamp) { curPod = pod } } return curPod, nil } ``` ```go // pkg/controller/controller_ref.go // GetControllerOf returns the controllerRef if controllee has a controller, // otherwise returns nil. func GetControllerOf(pod *k8sv1.Pod) *metav1.OwnerReference { controllerRef := metav1.GetControllerOf(pod) if controllerRef != nil { return controllerRef } // We may find pods that are only using CreatedByLabel and not set with an OwnerReference if createdBy := pod.Labels[virtv1.CreatedByLabel]; len(createdBy) > 0 { name := pod.Annotations[virtv1.DomainAnnotation] uid := types.UID(createdBy) vmi := virtv1.NewVMI(name, uid) return metav1.NewControllerRef(vmi, virtv1.VirtualMachineInstanceGroupVersionKind) } return nil } func IsControlledBy(pod *k8sv1.Pod, vmi *virtv1.VirtualMachineInstance) bool { if controllerRef := GetControllerOf(pod); controllerRef != nil { return controllerRef.UID == vmi.UID } return false } ``` The current logic assumes that a `virt-launcher` pod associated with a VMI may not always have a `controllerRef`. In such cases, the controller falls back to inspecting the pod's labels. Specifically it evaluates the `kubevirt.io/created-by` label, which is expected to match the UID of the VMI triggering the reconciliation loop. If multiple pods are found that could be associated with the same VMI, the `virt-controller` selects the most recently created one. This logic appears to be designed with migration scenarios in mind, where it is expected that two `virt-launcher` pods might temporarily coexist for the same VMI: one for the migration source and one for the migration target node. However, a scenario was not identified in which a legitimate `virt-launcher` pod lacks a `controllerRef` and relies solely on labels (such as `kubevirt.io/created-by`) to indicate its association with a VMI. This fallback behaviour introduces a security risk. If an attacker is able to obtain the UID of a running VMI and create a pod within the same namespace, they can assign it labels that mimic those of a legitimate `virt-launcher` pod. As a result, the `CurrentVMIPod` function could mistakenly return the attacker-controlled pod instead of the authentic one. This vulnerability has at least two serious consequences: • The attacker could disrupt or seize control over the VMI's lifecycle operations. • The attacker could potentially influence the VMI's migration target node, bypassing node-level security constraints such as `nodeSelector` or `nodeAffinity`, which are typically used to enforce workload placement policies. PoC _Complete instructions, including specific configuration details, to reproduce the vulnerability._ Consider the following VMI definition: ```yaml apiVersion: kubevirt.io/v1 kind: VirtualMachineInstance metadata: name: launcher-label-confusion spec: domain: devices: disks: • name: containerdisk disk: bus: virtio • name: cloudinitdisk disk: bus: virtio resources: requests: memory: 1024M terminationGracePeriodSeconds: 0 volumes: • name: containerdisk containerDisk: image: quay.io/kubevirt/cirros-container-disk-demo • name: cloudinitdisk cloudInitNoCloud: userDataBase64: SGkuXG4= ``` ```bash Deploy the launcher-label-confusion VMI operator@minikube:~$ kubectl apply -f launcher-confusion-labels.yaml Get the UID of the VMI operator@minikube:~$ kubectl get vmi launcher-label-confusion -o jsonpath='{.metadata.uid}' 18afb8bf-70c4-498b-aece-35804c9a0d11 Find the UID of the associated to the VMI `virt-launcher` pods (ActivePods) operator@minikube:~$ kubectl get vmi launcher-label-confusion -o jsonpath='{.status.activePods}' {"674bc0b1-e3c7-4c05-b300-9e5744a5f2c8":"minikube"} ``` The UID of the VMI can also be found as an argument to the container in the `virt-launcher` pod: ```bash Inspect the `virt-launcher` pod associated with the VMI and the --uid CLI argument with which it was launched operator@minikube:~$ kubectl get pods virt-launcher-launcher-label-confusion-bdkwj -o jsonpath='{.spec.containers[0]}' | jq . { "command": [ "/usr/bin/virt-launcher-monitor", ... "--uid", "18afb8bf-70c4-498b-aece-35804c9a0d11", "--namespace", "default", ... ``` Consider the following attacker-controlled pod which is associated to the VMI using the UID defined in the `kubevirt.io/created-by` label: ```yaml apiVersion: v1 kind: Pod metadata: name: fake-launcher labels: kubevirt.io: intruder # this is the label used by the virt-controller to identify pods associated with KubeVirt components kubevirt.io/created-by: 18afb8bf-70c4-498b-aece-35804c9a0d11 # this is the UID of the launcher-label-confusion VMI which is going to be taken into account if there is no ownerReference. This is the case f…

Related

Alias · CVE (1)

  • CVE-2025-64435 KubeVirt is a virtual machine management add-on for Kubernetes. vulnerability

Weakness · CWE (1)

  • CWE-703 Improper Check or Handling of Exceptional Conditions weakness

References