VYPR
Moderate severityNVD Advisory· Published Nov 7, 2025· Updated Nov 10, 2025

KubeVirt VMI Denial-of-Service (DoS) Using Pod Impersonation

CVE-2025-64435

Description

KubeVirt is a virtual machine management add-on for Kubernetes. Prior to 1.7.0-beta.0, 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). This vulnerability is fixed in 1.7.0-beta.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
kubevirt.io/kubevirtGo
< 1.7.0-beta.01.7.0-beta.0

Affected products

1

Patches

1
9a6f4a3a7079

Merge pull request #15680 from fossedihelm/do-not-use-only-label-for-pod

https://github.com/kubevirt/kubevirtkubevirt-botOct 1, 2025via ghsa
13 files changed · +31 75
  • pkg/controller/BUILD.bazel+0 1 modified
    @@ -5,7 +5,6 @@ go_library(
         srcs = [
             "conditions.go",
             "controller.go",
    -        "controller_ref.go",
             "controller_ref_manager.go",
             "expectations.go",
             "keys.go",
    
  • pkg/controller/controller.go+3 4 modified
    @@ -332,7 +332,7 @@ func CurrentVMIPod(vmi *v1.VirtualMachineInstance, podIndexer cache.Indexer) (*k
     
     	var curPod *k8sv1.Pod = nil
     	for _, pod := range pods {
    -		if !IsControlledBy(pod, vmi) {
    +		if !metav1.IsControlledBy(pod, vmi) {
     			continue
     		}
     
    @@ -366,7 +366,7 @@ func VMIActivePodsCount(vmi *v1.VirtualMachineInstance, vmiPodIndexer cache.Inde
     		if pod.Status.Phase == k8sv1.PodSucceeded || pod.Status.Phase == k8sv1.PodFailed {
     			// not interested in terminated pods
     			continue
    -		} else if !IsControlledBy(pod, vmi) {
    +		} else if !metav1.IsControlledBy(pod, vmi) {
     			// not interested pods not associated with the vmi
     			continue
     		}
    @@ -469,8 +469,7 @@ func AttachmentPods(ownerPod *k8sv1.Pod, podIndexer cache.Indexer) ([]*k8sv1.Pod
     	attachmentPods := []*k8sv1.Pod{}
     	for _, obj := range objs {
     		pod := obj.(*k8sv1.Pod)
    -		ownerRef := GetControllerOf(pod)
    -		if ownerRef == nil || ownerRef.UID != ownerPod.UID {
    +		if !metav1.IsControlledBy(pod, ownerPod) {
     			continue
     		}
     		attachmentPods = append(attachmentPods, pod)
    
  • pkg/controller/controller_ref.go+0 50 removed
    @@ -1,50 +0,0 @@
    -/*
    -Copyright 2016 The Kubernetes Authors.
    -Copyright 2017 The KubeVirt Authors.
    -
    -Licensed under the Apache License, Version 2.0 (the "License");
    -you may not use this file except in compliance with the License.
    -You may obtain a copy of the License at
    -
    -    http://www.apache.org/licenses/LICENSE-2.0
    -
    -Unless required by applicable law or agreed to in writing, software
    -distributed under the License is distributed on an "AS IS" BASIS,
    -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -See the License for the specific language governing permissions and
    -limitations under the License.
    -*/
    -
    -package controller
    -
    -import (
    -	k8sv1 "k8s.io/api/core/v1"
    -	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    -	"k8s.io/apimachinery/pkg/types"
    -
    -	virtv1 "kubevirt.io/api/core/v1"
    -)
    -
    -// 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
    -}
    
  • pkg/virt-controller/watch/dra/dra.go+5 5 modified
    @@ -190,7 +190,7 @@ func (c *DRAStatusController) addPod(obj interface{}) {
     		return
     	}
     
    -	controllerRef := controller.GetControllerOf(pod)
    +	controllerRef := metav1.GetControllerOf(pod)
     	vmi := c.resolveControllerRef(pod.Namespace, controllerRef)
     	if vmi == nil {
     		return
    @@ -218,7 +218,7 @@ func (c *DRAStatusController) deletePod(obj interface{}) {
     		}
     	}
     
    -	controllerRef := controller.GetControllerOf(pod)
    +	controllerRef := metav1.GetControllerOf(pod)
     	vmi := c.resolveControllerRef(pod.Namespace, controllerRef)
     	if vmi == nil {
     		return
    @@ -244,8 +244,8 @@ func (c *DRAStatusController) updatePod(old interface{}, cur interface{}) {
     		return
     	}
     
    -	curControllerRef := controller.GetControllerOf(curPod)
    -	oldControllerRef := controller.GetControllerOf(oldPod)
    +	curControllerRef := metav1.GetControllerOf(curPod)
    +	oldControllerRef := metav1.GetControllerOf(oldPod)
     	controllerRefChanged := !equality.Semantic.DeepEqual(curControllerRef, oldControllerRef)
     	if controllerRefChanged {
     		// The ControllerRef was changed. Sync the old controller, if any.
    @@ -275,7 +275,7 @@ func (c *DRAStatusController) resolveControllerRef(namespace string, controllerR
     			return nil
     		}
     		pod, _ := obj.(*k8sv1.Pod)
    -		controllerRef = controller.GetControllerOf(pod)
    +		controllerRef = metav1.GetControllerOf(pod)
     	}
     	// We can't look up by UID, so look up by Name and then verify UID.
     	// Don't even try to look up by Name if it is nil or the wrong Kind.
    
  • pkg/virt-controller/watch/drain/evacuation/evacuation_test.go+1 0 modified
    @@ -554,6 +554,7 @@ func newPod(vmi *v1.VirtualMachineInstance, name string, phase k8sv1.PodPhase, o
     		pod.Annotations = map[string]string{
     			v1.DomainAnnotation: vmi.Name,
     		}
    +		pod.OwnerReferences = []metav1.OwnerReference{*metav1.NewControllerRef(vmi, v1.VirtualMachineInstanceGroupVersionKind)}
     	}
     
     	return pod
    
  • pkg/virt-controller/watch/migration/migration_test.go+2 0 modified
    @@ -2371,6 +2371,7 @@ func newSourcePodForVirtualMachine(vmi *virtv1.VirtualMachineInstance) *k8sv1.Po
     			Annotations: map[string]string{
     				virtv1.DomainAnnotation: vmi.Name,
     			},
    +			OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(vmi, virtv1.VirtualMachineInstanceGroupVersionKind)},
     		},
     		Status: k8sv1.PodStatus{
     			Phase: k8sv1.PodRunning,
    @@ -2399,6 +2400,7 @@ func newTargetPodForVirtualMachine(vmi *virtv1.VirtualMachineInstance, migration
     				virtv1.DomainAnnotation:           vmi.Name,
     				virtv1.MigrationJobNameAnnotation: migration.Name,
     			},
    +			OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(vmi, virtv1.VirtualMachineInstanceGroupVersionKind)},
     		},
     		Status: k8sv1.PodStatus{
     			Phase: phase,
    
  • pkg/virt-controller/watch/node/node.go+2 2 modified
    @@ -388,7 +388,7 @@ func (c *Controller) alivePodsOnNode(nodeName string) ([]*v1.Pod, error) {
     
     	for i := range list.Items {
     		pod := &list.Items[i]
    -		if controllerRef := controller.GetControllerOf(pod); !isControlledByVMI(controllerRef) {
    +		if controllerRef := metav1.GetControllerOf(pod); !isControlledByVMI(controllerRef) {
     			continue
     		}
     
    @@ -425,7 +425,7 @@ func filterStuckVirtualMachinesWithoutPods(vmis []*virtv1.VirtualMachineInstance
     		if !ok {
     			podsForVMI = map[string]*v1.Pod{}
     		}
    -		if controllerRef := controller.GetControllerOf(pod); isControlledByVMI(controllerRef) {
    +		if controllerRef := metav1.GetControllerOf(pod); isControlledByVMI(controllerRef) {
     			podsForVMI[string(controllerRef.UID)] = pod
     			podsPerNamespace[pod.Namespace] = podsForVMI
     		}
    
  • pkg/virt-controller/watch/node/node_test.go+1 0 modified
    @@ -510,6 +510,7 @@ func NewHealthyPodForVirtualMachine(podName string, vmi *v1.VirtualMachineInstan
     				v1.CreatedByLabel: string(vmi.UID),
     				v1.AppLabel:       "virt-launcher",
     			},
    +			OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(vmi, v1.VirtualMachineInstanceGroupVersionKind)},
     		},
     		Spec: k8sv1.PodSpec{NodeName: vmi.Status.NodeName},
     		Status: k8sv1.PodStatus{
    
  • pkg/virt-controller/watch/vmi/lifecycle.go+5 5 modified
    @@ -873,7 +873,7 @@ func (c *Controller) deleteAllMatchingPods(vmi *virtv1.VirtualMachineInstance) e
     	}
     	vmiKey := controller.VirtualMachineInstanceKey(vmi)
     	for _, pod := range pods {
    -		if pod.DeletionTimestamp != nil && !isPodFinal(pod) || !controller.IsControlledBy(pod, vmi) {
    +		if pod.DeletionTimestamp != nil && !isPodFinal(pod) || !v1.IsControlledBy(pod, vmi) {
     			continue
     		}
     		if err = c.deletePod(vmiKey, pod, v1.DeleteOptions{}); err != nil {
    @@ -910,7 +910,7 @@ func (c *Controller) setActivePods(vmi *virtv1.VirtualMachineInstance) (*virtv1.
     	activePods := make(map[types.UID]string)
     	count := 0
     	for _, pod := range pods {
    -		if !controller.IsControlledBy(pod, vmi) {
    +		if !v1.IsControlledBy(pod, vmi) {
     			continue
     		}
     		count++
    @@ -929,7 +929,7 @@ func (c *Controller) allPodsDeleted(vmi *virtv1.VirtualMachineInstance) (bool, e
     		return false, err
     	}
     	for _, pod := range pods {
    -		if controller.IsControlledBy(pod, vmi) {
    +		if v1.IsControlledBy(pod, vmi) {
     			return false, nil
     		}
     	}
    @@ -1008,10 +1008,10 @@ func (c *Controller) waitForFirstConsumerTemporaryPods(vmi *virtv1.VirtualMachin
     		if !isTempPod(pod) {
     			continue
     		}
    -		if controller.IsControlledBy(pod, vmi) {
    +		if v1.IsControlledBy(pod, vmi) {
     			temporaryPods = append(temporaryPods, pod)
     		}
    -		if ownerRef := controller.GetControllerOf(pod); ownerRef != nil && ownerRef.UID == virtLauncherPod.UID {
    +		if v1.IsControlledBy(pod, virtLauncherPod) {
     			temporaryPods = append(temporaryPods, pod)
     		}
     	}
    
  • pkg/virt-controller/watch/vmi/vmi.go+5 5 modified
    @@ -351,7 +351,7 @@ func (c *Controller) addPod(obj interface{}) {
     		return
     	}
     
    -	controllerRef := controller.GetControllerOf(pod)
    +	controllerRef := v1.GetControllerOf(pod)
     	vmi := c.resolveControllerRef(pod.Namespace, controllerRef)
     	if vmi == nil {
     		return
    @@ -388,8 +388,8 @@ func (c *Controller) updatePod(old, cur interface{}) {
     		return
     	}
     
    -	curControllerRef := controller.GetControllerOf(curPod)
    -	oldControllerRef := controller.GetControllerOf(oldPod)
    +	curControllerRef := v1.GetControllerOf(curPod)
    +	oldControllerRef := v1.GetControllerOf(oldPod)
     	controllerRefChanged := !equality.Semantic.DeepEqual(curControllerRef, oldControllerRef)
     	if controllerRefChanged {
     		// The ControllerRef was changed. Sync the old controller, if any.
    @@ -428,7 +428,7 @@ func (c *Controller) onPodDelete(obj interface{}) {
     		}
     	}
     
    -	controllerRef := controller.GetControllerOf(pod)
    +	controllerRef := v1.GetControllerOf(pod)
     	vmi := c.resolveControllerRef(pod.Namespace, controllerRef)
     	if vmi == nil {
     		return
    @@ -506,7 +506,7 @@ func (c *Controller) resolveControllerRef(namespace string, controllerRef *v1.Ow
     			return nil
     		}
     		pod, _ := obj.(*k8sv1.Pod)
    -		controllerRef = controller.GetControllerOf(pod)
    +		controllerRef = v1.GetControllerOf(pod)
     	}
     	// We can't look up by UID, so look up by Name and then verify UID.
     	// Don't even try to look up by Name if it is nil or the wrong Kind.
    
  • pkg/virt-controller/watch/vmi/vmi_test.go+5 2 modified
    @@ -2432,7 +2432,7 @@ var _ = Describe("VirtualMachineInstance watcher", func() {
     		It("Should find vmi, from virt-launcher pod", func() {
     			vmi := newPendingVirtualMachine("testvmi")
     			pod := newPodForVirtualMachine(vmi, k8sv1.PodRunning)
    -			controllerRef := kvcontroller.GetControllerOf(pod)
    +			controllerRef := metav1.GetControllerOf(pod)
     			addVirtualMachine(vmi)
     
     			result := controller.resolveControllerRef(k8sv1.NamespaceDefault, controllerRef)
    @@ -2443,7 +2443,7 @@ var _ = Describe("VirtualMachineInstance watcher", func() {
     			vmi := newPendingVirtualMachine("testvmi")
     			pod := newPodForVirtualMachine(vmi, k8sv1.PodRunning)
     			attachmentPod := newPodForVirtlauncher(pod, "hp-test", "abcd", k8sv1.PodRunning)
    -			controllerRef := kvcontroller.GetControllerOf(attachmentPod)
    +			controllerRef := metav1.GetControllerOf(attachmentPod)
     			addVirtualMachine(vmi)
     			addPod(pod)
     
    @@ -4249,6 +4249,9 @@ func newPodForVirtualMachine(vmi *virtv1.VirtualMachineInstance, phase k8sv1.Pod
     				virtv1.CreatedByLabel: string(vmi.UID),
     			},
     			Annotations: podAnnotations,
    +			OwnerReferences: []metav1.OwnerReference{
    +				*metav1.NewControllerRef(vmi, virtv1.VirtualMachineInstanceGroupVersionKind),
    +			},
     		},
     		Status: k8sv1.PodStatus{
     			Phase: phase,
    
  • pkg/virt-controller/watch/vmi/volume-hotplug.go+1 1 modified
    @@ -315,7 +315,7 @@ func (c *Controller) deleteOrphanedAttachmentPods(vmi *v1.VirtualMachineInstance
     	}
     
     	for _, pod := range pods {
    -		if !controller.IsControlledBy(pod, vmi) {
    +		if !metav1.IsControlledBy(pod, vmi) {
     			continue
     		}
     
    
  • pkg/virt-controller/watch/workload-updater/workload-updater_test.go+1 0 modified
    @@ -747,6 +747,7 @@ func newLauncherPodForVMI(vmi *v1.VirtualMachineInstance) *k8sv1.Pod {
     			Annotations: map[string]string{
     				v1.DomainAnnotation: vmi.Name,
     			},
    +			OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(vmi, v1.VirtualMachineInstanceGroupVersionKind)},
     		},
     		Status: k8sv1.PodStatus{
     			Phase: k8sv1.PodRunning,
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.