Incus vulnerable to local privilege escalation through VM screenshot path
Description
Incus is a system container and virtual machine manager. Incus provides an API to retrieve VM screenshots. That API relies on the use of a temporary file for QEMU to write the screenshot to which is then picked up and sent to the user prior to deletion. As versions prior to 6.23.0 use predictable paths under /tmp for this, an attacker with local access to the system can abuse this mechanism by creating their own symlinks ahead of time. On the vast majority of Linux systems, this will result in a "Permission denied" error when requesting a screenshot. That's because the Linux kernel has a security feature designed to block such attacks, protected_symlinks. On the rare systems with this purposefully disabled, it's then possible to trick Incus intro truncating and altering the mode and permissions of arbitrary files on the filesystem, leading to a potential denial of service or possible local privilege escalation. Version 6.23.0 fixes the issue.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/lxc/incus/v6Go | < 6.23.0 | 6.23.0 |
Affected products
1Patches
1ef006240ac24incusd/instance_console: Prevent symlink attacks
1 file changed · +6 −6
cmd/incusd/instance_console.go+6 −6 modified@@ -726,14 +726,14 @@ func instanceConsoleLogGet(d *Daemon, r *http.Request) response.Response { var headers map[string]string if consoleLogType == "vga" { - screenshotFile, err := os.Create(fmt.Sprintf("/tmp/incus_screenshot_%d", inst.ID())) - if err != nil { - return response.SmartError(fmt.Errorf("Couldn't create screenshot file: %w", err)) - } + screenShotPath := fmt.Sprintf("/tmp/incus_screenshot_%d", inst.ID()) - err = screenshotFile.Chmod(0o600) + // Delete then create the path with O_EXCL to ensure that we are the creator of the path. + // Any attempt at racing with us will cause in a (already exists) failure. + _ = os.Remove(screenShotPath) + screenshotFile, err := os.OpenFile(screenShotPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o600) if err != nil { - return response.SmartError(err) + return response.SmartError(fmt.Errorf("Couldn't create screenshot file: %w", err)) } ent.Cleanup = func() {
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-q9vp-3wcg-8p4xghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-33711ghsaADVISORY
- github.com/lxc/incus/commit/ef006240ac2475ddea7b8406cecc7dbd1a883fdfghsaWEB
- github.com/lxc/incus/releases/tag/v6.23.0ghsaWEB
- github.com/lxc/incus/security/advisories/GHSA-q9vp-3wcg-8p4xghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.