Mend.io Vulnerability Database
The largest open source vulnerability database
What is a Vulnerability ID?
New vulnerability? Tell us about it!
CVE-2026-81497
Published:October 12, 2026
Updated:October 13, 2026
Summary The fix for CVE-2026-48752 ("GHSA-vxp5-584q-c479", template-traversal to host read/write, addressed in 7.2.0) was applied to the LXC container driver only. The sibling QEMU/VM driver's template path ("driver_qemu.go" → "templateApplyNow") never received the same guard, so its template read and write remain unbounded. An authenticated user who can create/launch a VM from a custom image, or restore a VM backup, controls the image/backup "metadata.yaml" (the "templates" map and each "tpl.Template" value) and can traverse out of the templates directory to: - read arbitrary host files as root, which are then disclosed into the guest, and - create root-owned files anywhere on the host (with a ".out" suffix). ### Details The LXC driver was hardened for CVE-2026-48752 ("internal/server/instance/drivers/driver_lxc.go"): "go os.OpenRoot(d.RootfsPath()) // ~:7493 confines writes if filepath.Base(tpl.Template) != tpl.Template // ~:7515 rejects any "/", blocks all "../" os.Lstat(d.TemplatesPath()) ... ModeSymlink // ~:7519 / ~:7533 rejects symlinked dir/source " The QEMU/VM driver received none of these. "driver_qemu.go" → "templateApplyNow" (func @ ":3712") has, before its file operations, only a "slices.Contains(tpl.When, trigger)" check. There is no path validation: "go // READ ~:3779 -- raw tpl.Template, no containment tplString, err := os.ReadFile(filepath.Join(d.TemplatesPath(), tpl.Template)) // WRITE ~:3765 -- raw tpl.Template, path is host-side under incusd (root) w, err = os.Create(filepath.Join(path, fmt.Sprintf("%s.out", tpl.Template))) " - READ vector: "tpl.Template = "../../../../etc/shadow"" reads an arbitrary host file, which is rendered into the VM config drive ("config/files/*.out", exported to the guest over 9p/virtiofs) → host-file disclosure to the attacker's guest. Cleanest, exact-path vector. - WRITE vector: "tpl.Template = "../../../../etc/cron.d/x"" creates "/etc/cron.d/x.out", a root-owned file anywhere on the host with pongo2-rendered content. A grep for "os.OpenRoot" / "OpenTemplates" over the templates directory in the incus QEMU path returns zero hits. Reachability: "templateApplyNow" is invoked from "generateConfigShare" on VM start, so the static call path is strong. Reference remediation. Apply incus's own LXC-driver guards (the "filepath.Base" reject + "os.OpenRoot" confinement) to "driver_qemu.go" → "templateApplyNow", covering both the read and the write. For the read specifically, upstream LXD is a second reference (it confines the QEMU read via "d.OpenTemplates()", an "os.Root"). Note that LXD does not confine the QEMU write either, so the write reference is incus's own LXC guard, not LXD. Scope / honesty. Source-confirmed via a white-box review of the public repo at fresh HEAD ("ccdf811") plus an LXD cross-reference; the guard absence was grep-verified. A live-VM end-to-end PoC is the documented next step. The read is a clean arbitrary host-file disclosure. The write is a genuine root-owned arbitrary-file-create primitive, but the created path is forced to carry a ".out" suffix, which constrains a direct write-to-RCE, so this is framed as High, not a 9.9 Critical, and no RCE is claimed without a ".out"-compatible execution path. ### PoC On a self-hosted incus 7.2.0 or later, craft a VM image whose "metadata.yaml" contains: "yaml templates: "/x": template: "../../../../../../tmp/incus-poc" when: - start " Launch the VM, then confirm on the host: "bash ls -l /tmp/incus-poc.out # created by incusd (root) = out-of-templates write " Separately, a "tpl.Template" of "../../etc/hostname" is read and disclosed into the guest config drive ("config/files/*.out"). ### Impact Path traversal (CWE-22) + link following (CWE-59) in the VM/QEMU template path. An authenticated user able to create/launch a VM from a custom image, or restore a VM backup, can: 1. read arbitrary host files as root, disclosed into their guest (e.g. "/etc/shadow"), and 2. create root-owned files with attacker-controlled content anywhere on the host (".out"-suffixed). Undisclosed. The authoritative public dissection ("Snyk Labs: Newlines, Symlinks, and Arbitrary Writes: Dissecting High-Severity Vulnerabilities in Incus" (https://labs.snyk.io/resources/incus-vulnerabilities-newline-symlink-arbitrary-writes/)) covers only "driver_lxc.go" and explicitly notes the VM drivers were not separately audited; no incus issue, PR, or CVE names "driver_qemu.go" → "templateApplyNow". --- Reporter: Kingsley Olukanni (GitHub: babakizo420).
Affected Packages
https://github.com/lxc/incus.git (GITHUB):
Affected version(s) >=v0.1.0 <v7.3.0
Fix Suggestion:
Update to version v7.3.0
github.com/lxc/incus (GO):
Affected version(s) >=v0.1.0 <v7.3.0
Fix Suggestion:
Update to version v7.3.0
github.com/lxc/incus/v7 (GO):
Affected version(s) >=v7.1.0 <v7.3.0
Fix Suggestion:
Update to version v7.3.0
Do you need more information?
Contact Us
CVSS v4
Base Score:
8.4
Attack Vector
NETWORK
Attack Complexity
LOW
Attack Requirements
NONE
Privileges Required
LOW
User Interaction
NONE
Vulnerable System Confidentiality
HIGH
Vulnerable System Integrity
LOW
Vulnerable System Availability
NONE
Subsequent System Confidentiality
HIGH
Subsequent System Integrity
LOW
Subsequent System Availability
NONE
CVSS v3
Base Score:
8.5
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
LOW
User Interaction
NONE
Scope
CHANGED
Confidentiality
HIGH
Integrity
LOW
Availability
NONE
Weakness Type (CWE)
Improper Link Resolution Before File Access ('Link Following')
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')