A flaw was found in KubeVirt's network cache handling in virt-handler. The WriteToCachedFile function in pkg/network/cache/cache.go writes network cache data to a path under /proc/<launcherPid>/root/var/run/kubevirt-private/ using os.WriteFile and then changes ownership using os.Chown. Neither operation uses ONOFOLLOW or the safepath package to prevent symlink traversal. Since virt-handler operates in the host mount namespace (only the network namespace is entered via setns), a symlink planted by a compromised virt-launcher process at the cache file path causes virt-handler to follow the symlink and write to an arbitrary host file, overwriting its content with JSON data and changing its ownership to uid 107. This constitutes a container-to-host file write primitive, though with constrained content (serialized JSON network cache data). The vulnerable code path is triggered only for bridge/non-masquerade interfaces (via the discoverbridge path in vm.go -> netconf.go -> cache.go). The default masquerade binding does not exercise this path.
A flaw was found in KubeVirt's network cache handling in virt-handler. The WriteToCachedFile function in pkg/network/cache/cache.go writes network cache data to a path under /proc/<launcherPid>/root/var/run/kubevirt-private/ using os.WriteFile and then changes ownership using os.Chown. Neither operation uses ONOFOLLOW or the safepath package to prevent symlink traversal. Since virt-handler operates in the host mount namespace (only the network namespace is entered via setns), a symlink planted by a compromised virt-launcher process at the cache file path causes virt-handler to follow the symlink and write to an arbitrary host file, overwriting its content with JSON data and changing its ownership to uid 107. This constitutes a container-to-host file write primitive, though with constrained content (serialized JSON network cache data). The vulnerable code path is triggered only for bridge/non-masquerade interfaces (via the discoverbridge path in vm.go -> netconf.go -> cache.go). The default masquerade binding does not exercise this path.
A flaw was found in KubeVirt's virt-handler domain notify server (pkg/virt-handler/notify-server/server.go). The gRPC handlers HandleDomainEvent (L54) and HandleK8SEvent (L96) derive the target VMI identity solely from the request body (DomainJSON informer key, EventNamespace/EventName) without validating it against the originating connection. Each virt-launcher connects via a per-VMI domain-notify-pipe.sock, but pipe.go performs a raw io.Copy byte pump with no peer identity tagging. No SOPEERCRED or per-connection authentication is present on the shared socket.
A compromised virt-launcher can connect to its own pipe socket and send HandleDomainEvent/HandleK8SEvent gRPC messages claiming to be any other VMI on the same node. virt-handler processes these as authoritative, updating the victim VMI's state in the Kubernetes API. This enables cross-tenant denial of service: forced shutdown/restart loops, lifecycle state corruption, and K8s Event forgery.
Upstream fix recommendation: Tag each pipe connection with the VMI UID at accept time (the pipe socket path already encodes it) and pass that identity through to the notify-server handlers; reject any DomainEvent/K8sEvent whose embedded namespace/name/UID does not match the connection's tagged identity.
References: - Vulnerable file: pkg/virt-handler/notify-server/server.go - Pipe handler: pkg/virt-handler/notify-server/pipe.go
A flaw was found in KubeVirt's virt-handler domain notify server (pkg/virt-handler/notify-server/server.go). The gRPC handlers HandleDomainEvent (L54) and HandleK8SEvent (L96) derive the target VMI identity solely from the request body (DomainJSON informer key, EventNamespace/EventName) without validating it against the originating connection. Each virt-launcher connects via a per-VMI domain-notify-pipe.sock, but pipe.go performs a raw io.Copy byte pump with no peer identity tagging. No SOPEERCRED or per-connection authentication is present on the shared socket.
A compromised virt-launcher can connect to its own pipe socket and send HandleDomainEvent/HandleK8SEvent gRPC messages claiming to be any other VMI on the same node. virt-handler processes these as authoritative, updating the victim VMI's state in the Kubernetes API. This enables cross-tenant denial of service: forced shutdown/restart loops, lifecycle state corruption, and K8s Event forgery.
Upstream fix recommendation: Tag each pipe connection with the VMI UID at accept time (the pipe socket path already encodes it) and pass that identity through to the notify-server handlers; reject any DomainEvent/K8sEvent whose embedded namespace/name/UID does not match the connection's tagged identity.
References: - Vulnerable file: pkg/virt-handler/notify-server/server.go - Pipe handler: pkg/virt-handler/notify-server/pipe.go
A flaw was found in KubeVirt's safepath package (pkg/safepath/safepathlinux.go). The OpenAtNoFollow function walks path components using OPATH|ONOFOLLOW flags, which per open(2) semantics succeeds on a symlink leaf and returns a file descriptor referring to the symlink itself rather than failing with ELOOP. Downstream helper functions (ChmodAtNoFollow, ChownAtNoFollow, MknodAtNoFollow) then operate on the path via /proc/self/fd/N using link-following syscalls (chown(2) instead of fchownat(ATSYMLINKNOFOLLOW)), which the kernel resolves by dereferencing the symlink at use time. This defeats the intended no-follow protection for the final path component.
An attacker with namespace-level pod access can place a symlink in the virt-launcher pod filesystem targeting an arbitrary host path. When virt-handler (running as root on the node) performs a safepath chown/chmod operation on that path during VM disk setup, hotplug, or network-cache flows, it follows the symlink and modifies the ownership or permissions of the attacker-chosen host file with hardcoded values (uid 107, mode ~0660).
A flaw was found in KubeVirt's virt-handler component. This vulnerability allows an authenticated OpenShift user with edit permissions in a single namespace to exploit improper symlink validation when connecting to virtual machine console sockets. By replacing the console socket with a symlink to the host's container runtime (CRI-O) socket, an attacker can hijack virt-handler's privileged connection. This enables the attacker to access any Unix socket on the host, potentially leading to full control of the node and the entire cluster.
A flaw was found in KubeVirt's virt-handler component. virt-handler connects to VM console sockets by following filesystem paths without validating symlinks. An authenticated OpenShift user with the standard edit role in a single namespace can exec into the virt-launcher pod, replace the console socket with a symlink pointing to the host's container runtime (CRI-O) socket, and hijack virt-handler's privileged connection. Since virt-handler runs with hostPID and elevated privileges, this allows the attacker to reach any unix socket on the host, potentially gaining full control of the node and cluster.