Kata guest escape: runtime-rs guest-root to host-root escape via virtiofs
Description
Summary
In the runtime-rs standalone virtio-fs path, verified here with QEMU (and verified with Cloud Hypervisor too), Kata Containers runs host virtiofsd as root with:
--sandbox none --seccomp none
If an attacker has root-equivalent execution inside the Kata guest VM, they can send raw FUSE requests directly to the host virtiofsd. With the tested runtime-rs virtio-fs configuration, a raw FUSE_SYMLINK request whose new symlink name is an absolute host path is honored outside the virtio-fs shared directory.
This lets guest root create host-root owned symlinks in sensitive host paths. The PoC created here will create symlinks in the host /etc/cron.d directory, causing host cron to execute a guest-controlled payload as host root.
Impact: guest root can execute code as host root.
Affected configuration
The verified host used:
/opt/kata/share/defaults/kata-containers/runtime-rs/configuration-qemu-runtime-rs.toml
rootless = false
shared_fs = "virtio-fs"
virtio_fs_daemon = "/opt/kata/libexec/virtiofsd"
hypervisor_name = "qemu"
debug_console_enabled = false
Pinned upstream references, using Kata Containers main commit 2ffd1538a296cff93a357bfba0dfca747480a1f8:
- runtime-rs standalone virtio-fs adds `--sandbox none --seccomp none` to the
virtiofsdcommand line. - runtime-rs QEMU leaves rootless mode disabled by default: `rootless = false`.
- The QEMU runtime-rs config template generates an installed config that uses standalone virtio-fs and points runtime-rs at the host
virtiofsdbinary: `shared_fs` and `virtio_fs_daemon`. - The runtime-rs Makefile resolves those placeholders to `virtio-fs` and `$(LIBEXECDIR)/virtiofsd`.
- runtime-rs selects the same standalone virtio-fs implementation whenever
shared_fs = "virtio-fs": `ShareVirtioFsStandalone`.
Details
The guest kernel normally owns the virtio-fs client. A normal guest process will use filesystem syscalls, and the guest kernel will validate the paths, and only then does the kernel send FUSE messages to the host backend.
An attacker with root-equivalent access inside the guest can bypass that guest virtio-fs client. They can access the virtio-fs PCI device, mmap the virtio PCI BAR, recover guest physical addresses from /proc/self/pagemap, and build their own virtqueue from userspace. That queue can submit attacker-built FUSE messages directly to host virtiofsd.
The relevant primitive is FUSE_SYMLINK. An attacker can send a request whose body contains:
new symlink name: /etc/cron.d/kata-go-escape-cron-
symlink target: /proc//root/run/kata-containers/shared/sandboxes//ro/passthrough//rootfs/tmp/kata-go-escape-payload
The new symlink name is an absolute host path. virtiofsd should reject that request or force it to resolve below the configured --shared-dir. In the tested runtime-rs path, host-root unsandboxed virtiofsd accepts the absolute name, creating a real host symlink under /etc/cron.d.
The attacker can make the symlink target resolve through /proc//root/... for a live Kata runtime process whose mount namespace can see the guest-created payload. One matching runtime PID is enough.
When the host cron reads /etc/cron.d, it follows the root-owned symlink, loads the guest-created crontab payload, and executes it as host root.
PoC
sudo timeout --foreground --kill-after=10s 600s ctr run --rm \
--runtime /opt/kata/runtime-rs/bin/containerd-shim-kata-v2 \
--runtime-config-path /opt/kata/share/defaults/kata-containers/runtime-rs/configuration-qemu-runtime-rs.toml \
--privileged \
--privileged-without-host-devices \
docker.io/library/kata-go-escape:local \
"$run_id"
The container is privileged only to model the post-escape condition where the attacker already has guest-root capabilities. It is not the vulnerability by itself.
Inside the guest, the PoC:
- Writes a cron payload to guest
/tmp/kata-go-escape-payload. - Finds the virtio-fs PCI device in guest /sys.
- Takes over a virtio-fs queue from userspace.
- Sends
FUSE_INIT. - Discovers the current runtime-rs sandbox under
passthrough/. - Looks up
passthrough//rootfs/tmp/kata-go-escape-payload. - Sends raw
FUSE_SYMLINKrequests where the new symlink names are absolute host paths under/etc/cron.d. - Keeps the guest alive while host cron scans.
Example log lines:
[guest] virtio-fs PCI device: /sys/devices/pci0000:00/0000:00:05.0
[res] sandbox_id=kata-go-escape-test-1778522686-1539
[res] lookup_path_error=0 path=passthrough/kata-go-escape-test-1778522686-1539/rootfs/tmp/kata-go-escape-payload nodeid=21
[spray] pid=1 err=-2 created_candidates=1
err=-2 is expected for the symlink spray. virtiofsd can return ENOENT after the side effect because its follow-up lookup is still relative to the export root. The host symlink creation has already happened.
Impact
The PoC proves guest-root to host-root command execution.
Verified host proof:
/run/kata-go-escape.proof
uid=0(root) gid=0(root) groups=0(root)
Mon May 11 18:05:01 UTC 2026
The proof file is written in host /run by host cron. It is not written by the guest process and not written by virtiofsd.
An attacker who reaches guest root can therefore cross the Kata isolation boundary and execute commands as host root on affected runtime-rs virtio-fs deployments.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Guest root can escape to host root by sending a raw FUSE_SYMLINK request through an unsandboxed virtiofsd in Kata Containers runtime-rs.
Vulnerability
In the runtime-rs standalone virtio-fs path of Kata Containers (verified with QEMU and Cloud Hypervisor), the host virtiofsd is launched with --sandbox none --seccomp none and runs as root [1][2][3]. When the configuration uses shared_fs = "virtio-fs", rootless = false, and the default virtio_fs_daemon path, the guest VM's root-equivalent attacker can send arbitrary raw FUSE requests directly to the host virtiofsd because the guest kernel's normal path validation is bypassed. This affects Kata Containers versions prior to the fix in release 3.31.0 (commit ffa59ce) [1][4].
Exploitation
An attacker with root-equivalent access inside the Kata guest VM can craft a raw FUSE_SYMLINK request whose new symlink name is an absolute host path (e.g., /etc/cron.d/evil). The unsandboxed host virtiofsd honors this request outside the intended virtio-fs shared directory, creating a host-root owned symlink on the host filesystem. The provided proof-of-concept targets /etc/cron.d to trigger host cron execution of a guest-controlled payload [2][3].
Impact
Successful exploitation allows a guest root attacker to execute arbitrary code as host root. By creating a symlink in a host directory such as /etc/cron.d, the attacker can cause the host's cron daemon to run a payload with full host root privileges, resulting in a complete host compromise [2][3].
Mitigation
The vulnerability is fixed in Kata Containers release 3.31.0 (commit ffa59ce) [1][4]. The fix also adds a security warning about the virtio_fs_extra_args annotation in runtime-rs configuration, recommending that it not be enabled unless all annotation sources are fully trusted [4]. Users should upgrade to version 3.31.0 or later. No workaround is available for unaffected configurations (i.e., those not using the runtime-rs standalone virtio-fs path with --sandbox none --seccomp none).
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/kata-containers/kata-containersGo | < 0.0.0-20260519062212-ffa59ce3aa78 | 0.0.0-20260519062212-ffa59ce3aa78 |
Affected products
2- Range: < 0.0.0-20260519062212-ffa59ce3aa78
Patches
2ffa59ce3aa78Merge commit from fork
4 files changed · +15 −7
docs/how-to/how-to-set-sandbox-config-kata.md+4 −2 modified@@ -49,9 +49,11 @@ Hypervisor annotations must be explicitly whitelisted in the Kata runtime config ```toml title="/path/to/configuration.toml" # List of valid annotation names for the hypervisor -enable_annotations = ["enable_iommu", "virtio_fs_extra_args", "kernel_params"] +enable_annotations = ["enable_iommu", "kernel_params"] ``` +Warning: do not enable `virtio_fs_extra_args` in `enable_annotations` unless you fully trust all annotation sources. Passing arbitrary `virtiofsd` options can be abused for malicious host-side behavior. + | Key | Value Type | Comments | |-------| ----- | ----- | | `io.katacontainers.config.hypervisor.asset_hash_type` | string | the hash type used for assets verification, default is `sha512` | @@ -107,7 +109,7 @@ enable_annotations = ["enable_iommu", "virtio_fs_extra_args", "kernel_params"] | `io.katacontainers.config.hypervisor.virtio_fs_cache_size` | uint32 | virtio-fs DAX cache size in `MiB` | | `io.katacontainers.config.hypervisor.virtio_fs_cache` | string | the cache mode for virtio-fs, valid values are `always`, `auto` and `never` | | `io.katacontainers.config.hypervisor.virtio_fs_daemon` | string | virtio-fs `vhost-user` daemon path | -| `io.katacontainers.config.hypervisor.virtio_fs_extra_args` | string | extra options passed to `virtiofs` daemon | +| `io.katacontainers.config.hypervisor.virtio_fs_extra_args` | string | extra options passed to `virtiofs` daemon. **Security warning:** enabling this annotation can be abused for malicious host-side behavior | | `io.katacontainers.config.hypervisor.enable_guest_swap` | `boolean` | enable swap in the guest | | `io.katacontainers.config.hypervisor.use_legacy_serial` | `boolean` | uses legacy serial device for guest's console (QEMU) | | `io.katacontainers.config.hypervisor.default_gpus` | uint32 | the minimum number of GPUs required for the VM. Only used by remote hypervisor to help with instance selection |
docs/runtime-configuration.md+3 −1 modified@@ -23,9 +23,11 @@ rootless = false # List of valid annotation names for the hypervisor # Each member of the list is a regular expression, which is the base name # of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path" -enable_annotations = ["enable_iommu", "virtio_fs_extra_args", "kernel_params"] +enable_annotations = ["enable_iommu", "kernel_params"] ``` +Warning: do not enable `virtio_fs_extra_args` in `enable_annotations` unless you fully trust all annotation sources. Allowing pods to pass `virtiofsd` extra arguments can be abused to inject unsafe daemon options and lead to malicious host-side behavior. + These files should never be modified directly. If you wish to create a modified version of these files, you may create your own [custom runtime](helm-configuration.md#custom-runtimes). For example, to modify the image path, we provide these values to helm: ```yaml title="values.yaml"
src/runtime/Makefile+4 −2 modified@@ -223,8 +223,10 @@ DEFMEMSLOTS := 10 DEFMAXMEMSZ := 0 #Default number of bridges DEFBRIDGES := 1 -DEFENABLEANNOTATIONS := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\"] -DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"] +# Security note: do not enable "virtio_fs_extra_args" by default. +# Allowing pods to pass arbitrary virtiofsd arguments can be abused for malicious host-side behavior. +DEFENABLEANNOTATIONS := [\"enable_iommu\", \"kernel_params\", \"kernel_verity_params\"] +DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"] DEFDISABLEGUESTSECCOMP := true DEFDISABLEGUESTEMPTYDIR := false DEFEMPTYDIRMODE := shared-fs
src/runtime-rs/Makefile+4 −2 modified@@ -174,8 +174,10 @@ DEFMAXMEMSZ := 0 DEFBRIDGES := 1 ##VAR DEFNETQUEUES=<number> Default number of network queues DEFNETQUEUES := 1 -DEFENABLEANNOTATIONS := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\"] -DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"] +# Security note: do not enable "virtio_fs_extra_args" by default. +# Allowing pods to pass arbitrary virtiofsd arguments can be abused for malicious host-side behavior. +DEFENABLEANNOTATIONS := [\"enable_iommu\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\"] +DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"] DEFDISABLEGUESTSECCOMP := true DEFDISABLEGUESTEMPTYDIR := false DEFEMPTYDIRMODE := shared-fs
ffa59ce3aa78Merge commit from fork
4 files changed · +15 −7
docs/how-to/how-to-set-sandbox-config-kata.md+4 −2 modified@@ -49,9 +49,11 @@ Hypervisor annotations must be explicitly whitelisted in the Kata runtime config ```toml title="/path/to/configuration.toml" # List of valid annotation names for the hypervisor -enable_annotations = ["enable_iommu", "virtio_fs_extra_args", "kernel_params"] +enable_annotations = ["enable_iommu", "kernel_params"] ``` +Warning: do not enable `virtio_fs_extra_args` in `enable_annotations` unless you fully trust all annotation sources. Passing arbitrary `virtiofsd` options can be abused for malicious host-side behavior. + | Key | Value Type | Comments | |-------| ----- | ----- | | `io.katacontainers.config.hypervisor.asset_hash_type` | string | the hash type used for assets verification, default is `sha512` | @@ -107,7 +109,7 @@ enable_annotations = ["enable_iommu", "virtio_fs_extra_args", "kernel_params"] | `io.katacontainers.config.hypervisor.virtio_fs_cache_size` | uint32 | virtio-fs DAX cache size in `MiB` | | `io.katacontainers.config.hypervisor.virtio_fs_cache` | string | the cache mode for virtio-fs, valid values are `always`, `auto` and `never` | | `io.katacontainers.config.hypervisor.virtio_fs_daemon` | string | virtio-fs `vhost-user` daemon path | -| `io.katacontainers.config.hypervisor.virtio_fs_extra_args` | string | extra options passed to `virtiofs` daemon | +| `io.katacontainers.config.hypervisor.virtio_fs_extra_args` | string | extra options passed to `virtiofs` daemon. **Security warning:** enabling this annotation can be abused for malicious host-side behavior | | `io.katacontainers.config.hypervisor.enable_guest_swap` | `boolean` | enable swap in the guest | | `io.katacontainers.config.hypervisor.use_legacy_serial` | `boolean` | uses legacy serial device for guest's console (QEMU) | | `io.katacontainers.config.hypervisor.default_gpus` | uint32 | the minimum number of GPUs required for the VM. Only used by remote hypervisor to help with instance selection |
docs/runtime-configuration.md+3 −1 modified@@ -23,9 +23,11 @@ rootless = false # List of valid annotation names for the hypervisor # Each member of the list is a regular expression, which is the base name # of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path" -enable_annotations = ["enable_iommu", "virtio_fs_extra_args", "kernel_params"] +enable_annotations = ["enable_iommu", "kernel_params"] ``` +Warning: do not enable `virtio_fs_extra_args` in `enable_annotations` unless you fully trust all annotation sources. Allowing pods to pass `virtiofsd` extra arguments can be abused to inject unsafe daemon options and lead to malicious host-side behavior. + These files should never be modified directly. If you wish to create a modified version of these files, you may create your own [custom runtime](helm-configuration.md#custom-runtimes). For example, to modify the image path, we provide these values to helm: ```yaml title="values.yaml"
src/runtime/Makefile+4 −2 modified@@ -223,8 +223,10 @@ DEFMEMSLOTS := 10 DEFMAXMEMSZ := 0 #Default number of bridges DEFBRIDGES := 1 -DEFENABLEANNOTATIONS := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\"] -DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"] +# Security note: do not enable "virtio_fs_extra_args" by default. +# Allowing pods to pass arbitrary virtiofsd arguments can be abused for malicious host-side behavior. +DEFENABLEANNOTATIONS := [\"enable_iommu\", \"kernel_params\", \"kernel_verity_params\"] +DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"] DEFDISABLEGUESTSECCOMP := true DEFDISABLEGUESTEMPTYDIR := false DEFEMPTYDIRMODE := shared-fs
src/runtime-rs/Makefile+4 −2 modified@@ -174,8 +174,10 @@ DEFMAXMEMSZ := 0 DEFBRIDGES := 1 ##VAR DEFNETQUEUES=<number> Default number of network queues DEFNETQUEUES := 1 -DEFENABLEANNOTATIONS := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\"] -DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"] +# Security note: do not enable "virtio_fs_extra_args" by default. +# Allowing pods to pass arbitrary virtiofsd arguments can be abused for malicious host-side behavior. +DEFENABLEANNOTATIONS := [\"enable_iommu\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\"] +DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"] DEFDISABLEGUESTSECCOMP := true DEFDISABLEGUESTEMPTYDIR := false DEFEMPTYDIRMODE := shared-fs
Vulnerability mechanics
Root cause
"virtiofsd, launched with --sandbox none --seccomp none, does not validate that the new symlink name in a FUSE_SYMLINK request stays within the configured shared directory, allowing an attacker inside the guest to create host-root-owned symlinks at arbitrary absolute host paths."
Attack vector
An attacker with root-equivalent execution inside the Kata guest VM bypasses the guest kernel's virtio-fs client by directly accessing the virtio-fs PCI device, mmapping the virtio PCI BAR, recovering guest physical addresses from /proc/self/pagemap, and building a userspace virtqueue [ref_id=1]. Through this queue the attacker submits a raw FUSE_SYMLINK request where the new symlink name is an absolute host path (e.g., /etc/cron.d/kata-go-escape-cron-<pid>) and the symlink target points through /proc/<pid>/root/... to a guest-controlled payload [ref_id=1]. Because virtiofsd runs as host root with --sandbox none --seccomp none, it honors the absolute path and creates a real host symlink outside the shared directory [ref_id=1]. Host cron then follows the symlink, loads the guest-created crontab payload, and executes it as host root [ref_id=1].
Affected code
The runtime-rs standalone virtio-fs path launches virtiofsd with --sandbox none --seccomp none in src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs (lines 82-92) [ref_id=1]. The runtime-rs configuration template (configuration-qemu-runtime-rs.toml.in) sets rootless = false, shared_fs = "virtio-fs", and points to the host virtiofsd binary [ref_id=1]. The patches modify src/runtime-rs/Makefile, src/runtime/Makefile, and documentation files to remove virtio_fs_extra_args from default enable_annotations [patch_id=2797570] [patch_id=2799076].
What the fix does
The patches [patch_id=2797570] [patch_id=2799076] remove "virtio_fs_extra_args" from the default enable_annotations lists in both the Go runtime and runtime-rs Makefiles, and update documentation to warn that enabling this annotation can be abused for malicious host-side behavior [ref_id=3]. This prevents pods from passing arbitrary extra arguments to virtiofsd via annotations, closing one avenue for injecting unsafe daemon options. The advisory notes that the underlying issue—virtiofsd accepting absolute symlink paths—is not directly fixed by this change; the patch reduces the attack surface by restricting annotation-based configuration injection.
Preconditions
- authAttacker must have root-equivalent execution inside the Kata guest VM
- configHost must use runtime-rs standalone virtio-fs path with virtiofsd running as root with --sandbox none --seccomp none
- configrootless must be false (default in runtime-rs QEMU configuration)
- networkAttacker must be able to access the virtio-fs PCI device from inside the guest and build a userspace virtqueue
- inputAttacker must craft a FUSE_SYMLINK request with an absolute host path as the new symlink name
Reproduction
```shell sudo timeout --foreground --kill-after=10s 600s ctr run --rm \ --runtime /opt/kata/runtime-rs/bin/containerd-shim-kata-v2 \ --runtime-config-path /opt/kata/share/defaults/kata-containers/runtime-rs/configuration-qemu-runtime-rs.toml \ --privileged \ --privileged-without-host-devices \ docker.io/library/kata-go-escape:local \ "$run_id" ``` Inside the guest, the PoC writes a cron payload to /tmp/kata-go-escape-payload, finds the virtio-fs PCI device, takes over a virtio-fs queue from userspace, sends FUSE_INIT, discovers the sandbox under passthrough/, looks up the payload path, and sends raw FUSE_SYMLINK requests with absolute host paths under /etc/cron.d [ref_id=1].
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-2gv2-cffp-j227ghsaADVISORY
- github.com/kata-containers/kata-containers/commit/ffa59ce3aa7877d067c9a372df0c329a23a01744ghsaWEB
- github.com/kata-containers/kata-containers/releases/tag/3.31.0ghsaWEB
- github.com/kata-containers/kata-containers/security/advisories/GHSA-2gv2-cffp-j227ghsaWEB
News mentions
0No linked articles in our index yet.