Introduction
A missing pair of entries in a hardcoded denylist is all it takes to turn a restricted LXD virtual machine user into a full host root administrator. CVE-2026-34177, scored at CVSS 9.1, exposes a privilege escalation path in Canonical LXD that chains an AppArmor rule injection with a QEMU configuration injection to bridge the LXD control socket directly into a guest VM.
LXD is Canonical's system container and virtual machine manager, providing a unified REST API for managing full Linux system images across bare metal and cloud infrastructure. It is widely deployed in multi tenant environments, CI/CD pipelines, and development platforms where project level restrictions are the primary isolation boundary. Canonical assumed direct stewardship of LXD from the Linux Containers community in July 2023 at version 5.15, and it ships as a default snap on Ubuntu Server installations.
Technical Information
Root Cause: Incomplete Denylist in VM Restriction Enforcement
The vulnerability lives in the isVMLowLevelOptionForbidden function within lxd/project/limits/permissions.go. When a project sets restricted.virtual-machines.lowlevel=block, this function is consulted to determine whether a given configuration key should be rejected. The function maintains a hardcoded list of forbidden keys, but that list omits two entries that are critical to VM confinement:
raw.apparmor: Permits injection of arbitrary AppArmor rules into the confinement profile applied to the QEMU process.raw.qemu.conf: Permits injection of arbitrary sections into the QEMU machine configuration file.
This is classified under CWE-184: Incomplete List of Disallowed Inputs.
What makes this particularly notable is that the container equivalent function, isContainerLowLevelOptionForbidden, does correctly include raw.apparmor in its forbidden list. The VM function simply never received the same treatment, a parity lapse that went unnoticed across multiple release cycles from version 4.12 through 6.7.
The patched version of the function adds both missing keys:
func isVMLowLevelOptionForbidden ( key string ) bool { return slices. Contains ( string { "boot.host_shutdown_timeout", "limits.memory.hugepages", "raw.apparmor", "raw.idmap", "raw.qemu", "raw.qemu.conf", }, key ) }
Attack Flow
An attacker needs can_edit permissions on a virtual machine instance within a restricted project. This is a legitimate permission level in multi tenant LXD deployments. The exploitation chain proceeds through five stages:
Stage 1: AppArmor Rule Injection. The attacker sets the raw.apparmor configuration key on their VM. The injected rule grants the QEMU process read and write access to the LXD Unix socket located at /var/snap/lxd/common/lxd/unix.socket. Because the denylist does not block raw.apparmor, the LXD API accepts this configuration without complaint.
Stage 2: QEMU Configuration Injection. The attacker sets the raw.qemu.conf configuration key to add two elements to the QEMU machine definition: a chardev section that points to the LXD Unix socket, and a device section that creates a virtserialport connected to that chardev. Again, the denylist does not block this key.
Stage 3: Socket Bridging on VM Startup. When the virtual machine starts (or restarts), QEMU opens a connection to the LXD Unix socket on the host and exposes it inside the guest as /dev/virtio-ports/lxd.exploit. At this point, the guest VM has a direct, authenticated communication channel to the LXD daemon running on the host.
Stage 4: Privilege Escalation to Cluster Administrator. From inside the guest, the attacker sends a single HTTP request through the bridged socket to add the admin entitlement to their own group. The LXD daemon processes this request as if it came from a local, trusted client because the connection arrives over the Unix socket.
Stage 5: Host Root Access. With cluster administrator privileges, the attacker creates a privileged container, mounts the host root filesystem into it, and obtains full host root access.
CVSS Metrics
The CVSS v3.1 vector reflects the severity of this chain:
| Metric | Value | Operational Implication |
|---|---|---|
| Attack Vector | Network | Exploitable remotely via the LXD API |
| Attack Complexity | Low | The exploit is trivial and requires no misconfiguration |
| Privileges Required | High | Requires can_edit permissions on a virtual machine |
| User Interaction | None | No interaction from other users is needed |
| Scope | Changed | The attack escapes the virtual machine to compromise the host |
| Confidentiality | High | Full access to host data |
| Integrity | High | Full ability to modify host systems |
| Availability | High | Full ability to disrupt host operations |
The "Changed" scope is the key driver of the 9.1 score. This is not a vulnerability that stays contained within the VM boundary; it crosses from guest to host and from restricted user to root.
Affected Systems and Versions
The vulnerability affects Canonical LXD versions 4.12 through 6.7. Any deployment that relies on the restricted.virtual-machines.lowlevel=block project restriction for multi tenant isolation is vulnerable.
Canonical has released patched versions across all supported series:
| LXD Series | Interim Snap Release | Final Patched Version |
|---|---|---|
| Series 6 | 6.7 d814d89 | 6.8 |
| Series 5.21 LTS | 5.21.4 aee7e08 | 5.21.5 |
| Series 5.0 LTS | 5.0.6 7fc3b36 | 5.0.7 |
| Series 4.0 LTS | 4.0.10 e92d947 | Not specified in advisory |
Deployments that do not use restricted projects, or that do not grant can_edit permissions to untrusted users on VM instances, have reduced exposure but should still patch.
Vendor Security History
Canonical demonstrated responsible handling of this disclosure. Interim snap fixes were coordinated and released across four supported branches between March 27 and March 30, 2026, well ahead of the public advisory on April 9, 2026. The same update cycle also bundled fixes for other critical vulnerabilities, including a TLS certificate privilege escalation and a backup import restriction bypass, suggesting that Canonical conducted a broader security audit of the LXD project restrictions subsystem in response to this report.
The vulnerability was responsibly disclosed by a researcher identified as mpurg.
References
- GitHub Security Advisory: GHSA-fm2x-c5qw-4h6f
- Pull Request #17909: Prevent use of raw.apparmor and raw.qemu.conf when low level options are blocked
- CWE-184: Incomplete List of Disallowed Inputs
- LXD 6.7 Interim Snap Release 6.7-d814d89
- LXD 5.21.4 LTS Interim Snap Release 5.21.4-aee7e08
- LXD 5.0.6 LTS Interim Snap Release 5.0.6-7fc3b36
- LXD 4.0.10 LTS Interim Snap Release 4.0.10-e92d947
- LXD Documentation



