Incus Backup Import: ../ in a Volume Name, Root on the Host (CVE-2026-115375)
your multi-tenant container host trusted the filename in a backup. bold. Incus before 7.5 validated the instance name on import, then took dependent custom volume names from index.yaml and fed them to filepath.Join like they were housebroken. a ../ chain later, the root daemon is writing attacker content outside the storage pool. CVE-2026-115375. GHSA-hpjh-q53p-f27r. fixed in 7.5.0 / 7.5.1. eleven security fixes in that release. this is the one that makes tenants into landlords.
what landed
- CVE-2026-115375 / GHSA-hpjh-q53p-f27r: path traversal in instance backup dependent custom volume names.
- Related: CVE-2026-115377 (symlink in migration/rsync stream), CVE-2026-115378 and friends in the same 7.5 security bundle. same release train, different shapes of “root writes where it should not.”
- Affected: Incus before 7.5.0 (NVD notes 7.0.0 before 7.0.2 and 7.1.0 before 7.5.0 for this specific CVE).
- Patched: 7.5.0 / 7.5.1 (7.5.0 had artifact issues; download 7.5.1).
- CVSS: advisory 9.9 (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H). NVD ~9.4.
- CWE: CWE-22 / CWE-23 (path traversal).
the bug in one paragraph
fixes for earlier backup-name CVEs taught Incus to validate instance names and direct custom-volume import names. the dependent-volume list nested inside an instance backup did not go through those checks. names from backup/index.yaml became path segments under the storage pool. filepath.Join collapses ../. os.Mkdir and the volume unpack then run as the Incus daemon. the daemon is root. you see where this is going.

step 1: craft the backup
an instance backup tarball carries backup/index.yaml plus rootfs and any dependent custom volumes. the advisory path:
volumes:
- name: ../../../outside-pool/pwned-vol
type: custom
pool: default
project: default
on a real host the traversal aims at something useful: /etc/cron.d/, a systemd drop-in, an authorized_keys path, a web root. in lab we point it at a sibling directory outside the fake pool so the screenshot is honest about “outside” without pretending we rooted a cluster.
bonus cruelty from the advisory: the backup also names the project each dependent volume is created in, so the same request can create volumes in projects the caller should not touch.

step 2: Join is not a security boundary
pool path looks like .../storage-pools/default/custom. volume name ../../../outside-pool/pwned-vol joins into a path that leaves that tree. no IsAPIName, no clean-and-contain check on this branch in the affected builds. the attached-device gate can be satisfied by splitting the traversal across device pool and source fields. once the directory exists, volume contents unpack into it.
filepath.Join(pool, "../../../outside-pool/pwned-vol")
# => .../outside-pool/pwned-vol (outside the pool)

step 3: impact
any client allowed to create instances in a project can make the daemon create root-owned directories and drop attacker-controlled content at arbitrary host paths. that is full host compromise from a “backup import” button. multi-tenant Incus with untrusted project users is the nightmare configuration. single-admin homelab with no remote create rights is a much smaller fish, but still patch it before you invite friends.
why defenders care
- incomplete fix residue: earlier name-validation CVEs left a nested path unchecked. patch one door, check the hallway.
- root daemon: Incus has to manage storage. that privilege is why a path bug becomes host RCE instead of a sad 403.
- tenant to host: “project isolation” is a product claim. this bug turns it into a slide deck.
- 7.5 ships a pile: eleven security fixes. if you are still on 7.2 because “it was fine,” update your definition of fine.
controls that are not theater
- upgrade to Incus 7.5.1 (or current) on every cluster node. staging first if you must, but do not schedule this for next quarter.
- only trusted principals get
can_create_instances/ backup import rights. “every developer in the org” is not a threat model, it is a wish. - monitor for Incus creating paths outside configured storage pool roots (auditd, fanotify, IMA, take your pick).
- treat backup import as code execution: scan, stage, review. especially backups that did not originate on your infrastructure.
- network-isolate the Incus API. project users should not be poking the daemon from the coffee shop VPN without MFA and a ticket.
sloth take
you validated the front door name and left the volume names in the moving boxes unchecked. the boxes had ../ in the address. the root daemon delivered them anyway. upgrade to 7.5.1. stop letting untrusted clients create instances. and maybe, just maybe, stop treating backup import as a boring file copy.
sources
- GitHub Advisory GHSA-hpjh-q53p-f27r
- CVE-2026-115375 (see also CVE-2026-115377)
- Incus 7.5 release notes (security fixes list; install 7.5.1)
