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



CVE-2026-12411

CVE-2026-12411: Cross-Guest Volume Hijack via DevLXD Device PATCH in Canonical LXD

Amit Schendel
Amit Schendel
Senior Security Researcher

Nov 5, 2026·10 min read·1 visit

Executive Summary (TL;DR)

An authorization bypass in Canonical LXD (versions 6.6 to 6.8) allows a guest instance with DevLXD volume management enabled to mount, read, and modify custom storage volumes belonging to other guests or identities by submitting a crafted device PATCH request over the /dev/lxd socket.

CVE-2026-12411 is a broken access control vulnerability in the DevLXD interface of Canonical LXD versions 6.6 through 6.8. The flaw resides in the devLXDInstancePatchHandler component, which fails to verify storage volume ownership when an instance attaches a new disk device via the /dev/lxd guest socket. When the security.devlxd.management.volumes configuration option is enabled, an untrusted guest or DevLXD identity can issue a crafted HTTP PATCH request referencing another tenant's custom storage volume. The LXD host daemon subsequently mounts the target volume into the requesting guest, permitting unauthorized cross-tenant read and write operations.

Vulnerability Overview

Canonical LXD provides a system container and virtual machine manager built on top of Linux containers (LXC) and QEMU. To facilitate guest-to-host communication without requiring network access to the primary LXD daemon API, LXD exposes a Unix domain socket at /dev/lxd inside guest instances. This interface, known as DevLXD, allows guests to query instance metadata, retrieve configuration properties, and—when specific security flags are enabled—manage guest-specific resources such as custom storage volumes.

In LXD 6.6, Canonical introduced expanded DevLXD capabilities allowing guests to self-manage custom storage volumes when the instance configuration key security.devlxd.management.volumes is set to true. Access control within this subsystem relies on fine-grained DevLXD identities (devlxd/<identity-name>) authenticated via bearer tokens. Each custom storage volume created or managed through DevLXD records its owning identity within the volume metadata key volatile.devlxd.owner.

CVE-2026-12411 (classified under CWE-639 and CWE-862) is an authorization bypass in the devLXDInstancePatchHandler function within lxd/devlxd_instances.go. While the DevLXD storage volume endpoints properly enforce ownership checks when querying or modifying volumes directly, the instance device management endpoint failed to verify whether the requesting identity owned the underlying storage volume referenced in a new disk device attachment.

Consequently, an authenticated DevLXD identity with permission to edit its host instance can submit an HTTP PATCH request to /dev/lxd that defines a new disk device pointing to an arbitrary custom volume name and storage pool within the same project. The LXD daemon processes the device addition and mounts the target volume into the guest filesystem, bypassing tenant isolation boundaries and granting the caller complete read and write access to the victim volume's contents.

Root Cause Analysis

The root cause of CVE-2026-12411 is an incomplete authorization check during the evaluation of instance device updates in generateDevLXDInstanceDevices. When a guest submits an HTTP PATCH request to update its device configuration via /dev/lxd, the request is routed to devLXDInstancePatchHandler. This handler extracts the caller's identity (requestor.Username) and invokes generateDevLXDInstanceDevices to validate the requested device modifications and compute the updated instance configuration.

In vulnerable versions of LXD (6.6 through 6.8), generateDevLXDInstanceDevices iterated through each device in the incoming request payload (req.Devices) and checked whether the device name already existed in the instance's expanded device map (inst.ExpandedDevices[name]). The authorization guard was implemented as if (exists && !isOwned) || (!isDeviceAccessible(device)). Here, isOwned verified whether an existing attached device belonged to the caller by inspecting volatile.<device-name>.devlxd.owner in the instance configuration.

When an attacker attached a new device under an unused device key, exists evaluated to false, completely bypassing the !isOwned condition. The security check then relied exclusively on isDeviceAccessible(device), a closure generated by newDevLXDDeviceAccessValidator(inst). However, newDevLXDDeviceAccessValidator only verified two static properties: whether security.devlxd.management.volumes was enabled on the instance (diskDeviceAllowed), and whether the submitted device map syntactically matched a custom volume disk definition (filters.IsCustomVolumeDisk(device)).

Because neither generateDevLXDInstanceDevices nor isDeviceAccessible queried the LXD database to verify the volatile.devlxd.owner property of the target storage volume (device["source"] inside device["pool"]), the authorization check succeeded unconditionally for any valid custom volume name. Furthermore, once the check passed, LXD recorded the new device attachment in the instance configuration as owned by the attacker (newConfig["volatile."+name+".devlxd.owner"] = identityID) and instructed the host storage driver to mount the volume into the guest.

Code Analysis

The vulnerability and its remediation are located in lxd/devlxd_instances.go. In the vulnerable implementation prior to LXD 6.9, newDevLXDDeviceAccessValidator returned a boolean function that inspected only instance-level feature flags and device map fields without database or context awareness.

// Vulnerable implementation in lxd/devlxd_instances.go (LXD 6.6 - 6.8)
type devLXDDeviceAccessValidator func(device map[string]string) bool
 
func newDevLXDDeviceAccessValidator(inst instance.Instance) devLXDDeviceAccessValidator {
	diskDeviceAllowed := hasInstanceSecurityFeatures(inst.ExpandedConfig(), devLXDSecurityManagementVolumesKey)
	return func(device map[string]string) bool {
		// Only verifies instance config flag and device type/syntax
		return diskDeviceAllowed && filters.IsCustomVolumeDisk(device)
	}
}
 
func generateDevLXDInstanceDevices(inst api.Instance, req api.DevLXDInstancePut, identityID string, isDeviceAccessible devLXDDeviceAccessValidator) (devices map[string]map[string]string, config map[string]string, err error) {
	// ...
	for name, device := range req.Devices {
		// ...
		_, exists := inst.ExpandedDevices[name]
 
		// BUG: If exists is false (new device attachment), !isOwned is not evaluated,
		// and isDeviceAccessible does not check who owns device["source"].
		if (exists && !isOwned) || (!isDeviceAccessible(device)) {
			return nil, nil, api.StatusErrorf(http.StatusForbidden, "Not authorized to manage device %q", name)
		}
		// ...
	}
}

In commit 7cb96ac80a6d52a96b53b0ae06a8659606fa8dd8, Canonical remediated the flaw by modifying devLXDDeviceAccessValidator to return an error and introducing a second validator function, newDevLXDDeviceResourceOwnershipValidator. This new validator is passed into generateDevLXDInstanceDevices as isDeviceResourceOwned.

// Patched implementation in lxd/devlxd_instances.go (LXD 6.9+)
type devLXDDeviceAccessValidator func(device map[string]string) error
 
func devLXDInstancePatchHandler(d *Daemon, r *http.Request) response.Response {
	// ...
	deviceChecker := newDevLXDDeviceAccessValidator(inst)
	deviceResourceOwnershipChecker := newDevLXDDeviceResourceOwnershipValidator(r.Context(), d, projectName)
	devices, config, err := generateDevLXDInstanceDevices(targetInst, reqInst, requestor.Username, deviceChecker, deviceResourceOwnershipChecker)
	if err != nil {
		return response.DevLXDErrorResponse(err)
	}
	// ...
}
 
func newDevLXDDeviceResourceOwnershipValidator(ctx context.Context, d *Daemon, projectName string) devLXDDeviceAccessValidator {
	return func(device map[string]string) error {
		poolName := device["pool"]
		volName := device["source"]
 
		if poolName == "" || volName == "" {
			return api.StatusErrorf(http.StatusBadRequest, "Invalid device configuration: Missing pool or volume name")
		}
 
		// Construct internal API request to resolve storage volume details within the caller's context
		url := api.NewURL().Path("1.0", "storage-pools", poolName, "volumes", "custom", volName).Project(projectName)
		req, err := lxd.NewRequestWithContext(ctx, http.MethodGet, url.String(), nil, "")
		if err != nil {
			return api.StatusErrorf(http.StatusInternalServerError, "Failed creating request: %w", err)
		}
 
		req.SetPathValue("type", "custom")
		req.SetPathValue("poolName", poolName)
		req.SetPathValue("volumeName", volName)
 
		err = addStoragePoolVolumeDetailsToRequestContext(d.State(), req)
		if err != nil {
			return err
		}
 
		// Retrieve volume via devLXDStoragePoolVolumeGet to enforce volatile.devlxd.owner verification
		_, _, err = devLXDStoragePoolVolumeGet(req.Context(), d, "", projectName, poolName, volName, "custom")
		if err != nil {
			return err
		}
 
		return nil
	}
}

The fix is architectural and complete for custom volume disk attachments. Rather than duplicating ownership logic, newDevLXDDeviceResourceOwnershipValidator synthesizes an internal HTTP GET request carrying the caller's r.Context() (which contains the authenticated DevLXD identity) and delegates verification to devLXDStoragePoolVolumeGet. If the target volume does not exist or its volatile.devlxd.owner metadata does not match the requesting identity, devLXDStoragePoolVolumeGet returns an error, halting device generation before any host storage operations occur.

Exploitation

Exploiting CVE-2026-12411 requires local execution inside an LXD container or virtual machine where security.devlxd.management.volumes=true is configured. Additionally, the attacker must possess a valid DevLXD bearer token associated with an identity (devlxd/<identity>) that has been granted can_edit permissions on the instance and storage_volume_manager permissions within the project. The attacker also needs to know or guess the target storage pool name and the victim's custom volume name.

In a multi-tenant or shared identity scenario, suppose a legitimate identity (devlxd/victim-identity) creates a custom storage volume named victim-secret-vol in the pool test-pool over /dev/lxd. LXD sets volatile.devlxd.owner: devlxd/victim-identity on victim-secret-vol. When a second, untrusted identity (devlxd/attacker-identity) attempts to read or delete victim-secret-vol through the /dev/lxd/1.0/storage-pools/test-pool/volumes/custom/victim-secret-vol endpoint, LXD rejects the request.

To bypass this restriction, devlxd/attacker-identity targets the instance configuration endpoint via an HTTP PATCH request over /dev/lxd (or by invoking the devlxd-client instance update utility). The attacker submits a JSON payload defining a new disk device (e.g., hijacked-vol) that specifies pool: test-pool, source: victim-secret-vol, and an arbitrary guest mount path such as /mnt/hijacked-secret-data.

# 1. Construct the malicious device PATCH payload targeting the victim's volume
ATTACK_PAYLOAD=$(cat <<EOF
{
    "devices": {
        "hijacked-vol": {
            "type": "disk",
            "pool": "test-pool",
            "source": "victim-secret-vol",
            "path": "/mnt/hijacked-secret-data"
        }
    }
}
EOF
)
 
# 2. Submit the PATCH request over /dev/lxd using the attacker's bearer token
lxc exec guest-attacker --project test-project --env DEVLXD_BEARER_TOKEN="${TOKEN_ATTACKER}" -- \
    devlxd-client instance update guest-attacker "${ATTACK_PAYLOAD}"

Upon receiving this payload, a vulnerable LXD daemon (< 6.9) verifies that hijacked-vol is a new device key on guest-attacker and confirms that the JSON structure matches a custom disk volume. It then attaches victim-secret-vol to guest-attacker and mounts it at /mnt/hijacked-secret-data, granting processes inside the guest immediate filesystem-level read and write access to the victim's volume.

Impact Assessment

CVE-2026-12411 carries a CVSS v3.1 base score of 8.4 (High) with the vector CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N. The Attack Vector is Local (AV:L) and Privileges Required is Low (PR:L) because exploitation originates from inside an allocated guest instance using a provisioned DevLXD token. Attack Complexity is Low (AC:L) and requires no user interaction (UI:N), as the attack relies on a single deterministic API request.

The Scope is Changed (S:C) because the vulnerability resides in the host-managed LXD daemon and allows an untrusted guest identity to cross security boundaries and access storage resources belonging to other tenants or identities within the same LXD project. Both Confidentiality (C:H) and Integrity (I:H) impacts are High.

Once the unauthorized custom volume is mounted into the attacker's guest instance, the attacker can read sensitive application data, credentials, or keys stored on the volume. Furthermore, because the volume is mounted read-write by default, the attacker can modify, corrupt, or delete files on the volume, directly compromising the integrity of any other instance relying on that storage volume.

> [!NOTE] > While the CVSS Availability metric is rated None (A:N) with respect to the host daemon itself, an attacker with write access to the mounted filesystem can delete all data on the victim volume, causing data loss and service disruption for the legitimate volume owner.

According to FIRST EPSS metrics, CVE-2026-12411 has an exploitation probability score of 0.00288 (21.48th percentile) and is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog. The prerequisite that security.devlxd.management.volumes must be explicitly enabled limits exposure on default deployments, concentrating risk in cloud or container hosting environments that delegate storage volume management to guest instances.

Remediation

Canonical addressed CVE-2026-12411 in LXD version 6.9 via pull request #18585 and commit 7cb96ac80a6d52a96b53b0ae06a8659606fa8dd8. Administrators running LXD versions 6.6, 6.7, or 6.8 should upgrade to LXD 6.9 or later immediately. On systems where LXD is deployed via Snap, the daemon can be updated using the standard channel refresh command:

sudo snap refresh lxd --channel=latest/stable

If an immediate upgrade is not operationally feasible, administrators can mitigate the vulnerability by disabling DevLXD volume self-management across all instances. Removing or setting security.devlxd.management.volumes to false causes newDevLXDDeviceAccessValidator to reject all disk device modification requests originating from /dev/lxd.

# Audit all instances across projects to identify where volume management is enabled
lxc list -c n,c -f json | jq '.[] | select(.config["security.devlxd.management.volumes"] == "true") | .name'
 
# Disable DevLXD volume management on a vulnerable instance
lxc config unset <instance-name> security.devlxd.management.volumes

In addition to disabling the configuration key, security teams should review active DevLXD authentication identities and revoke unnecessary can_edit instance permissions or storage_volume_manager project permissions. Administrators should also audit existing instance configurations for unexpected volatile.<device-name>.devlxd.owner entries and cross-reference attached disk source values against the volatile.devlxd.owner metadata of the corresponding custom storage volumes to detect prior unauthorized attachments.

Official Patches

CanonicalPull Request #18585: Security fixes from the 6.9 release
CanonicalPatch commit fixing DevLXD device resource ownership validation
CanonicalGitHub Security Advisory GHSA-hhf9-qw4v-72xp

Fix Analysis (1)

Technical Appendix

CVSS Score
8.4/ 10
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N
EPSS Probability
0.29%
Top 79% most exploited

Affected Systems

Canonical LXD

Affected Versions Detail

Product
Affected Versions
Fixed Version
LXD
Canonical
>= 6.6, < 6.96.9
AttributeDetail
CVE IDCVE-2026-12411 (GHSA-hhf9-qw4v-72xp)
Weakness ClassCWE-639 (Authorization Bypass Through User-Controlled Key) / CWE-862
Affected VersionsCanonical LXD >= 6.6, < 6.9
Attack VectorLocal via /dev/lxd socket (AV:L/AC:L/PR:L/UI:N)
CVSS v3.1 Score8.4 High (Scope Changed, High Confidentiality & Integrity Impact)
EPSS Score0.29% (0.00288 - 21.48th percentile)
Exploit StatusFunctional PoC in upstream test suite (Not in CISA KEV)
Patched VersionCanonical LXD 6.9

MITRE ATT&CK Mapping

T1068Exploitation for Privilege Escalation
Privilege Escalation
CWE-639
Authorization Bypass Through User-Controlled Key

The system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data.

Known Exploits & Detection

GitHub (Canonical LXD Upstream Integration Test)Upstream regression test in test/suites/devlxd.sh demonstrating cross-identity volume attachment via devlxd-client instance update.

Vulnerability Timeline

Upstream security commit authored by Canonical (din.music@canonical.com) introducing devLXD device resource ownership validation.
2026-06-15
Canonical security pull request #18585 merged and LXD 6.9 release tagged.
2026-06-26
CVE-2026-12411 and GitHub Security Advisory GHSA-hhf9-qw4v-72xp published by Canonical CNA.
2026-06-26
NVD entry published and CVSS v3.1 base score of 8.4 assigned.
2026-06-26
NVD record metadata updated.
2026-10-25
EPSS score recorded at 0.00288 (21.48th percentile).
2026-11-05

References & Sources

  • [1]CVE-2026-12411 Official CVE Record
  • [2]NVD - CVE-2026-12411 Detail
  • [3]GitHub Security Advisory GHSA-hhf9-qw4v-72xp
  • [4]Canonical LXD Pull Request #18585: Security fixes from the 6.9 release
  • [5]Canonical LXD Fix Commit 7cb96ac80a6d52a96b53b0ae06a8659606fa8dd8
  • [6]Canonical LXD GitHub Repository
  • [7]CVEListV5 Record for CVE-2026-12411

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 3 hours ago•CVE-2026-105769
9.3

CVE-2026-105769: Azure Entra ID Token Exfiltration in Kaniko via Unanchored ACR Hostname Regex

CVE-2026-105769 (GHSA-5q7h-w9jf-cx97, GO-2026-6225) is an origin validation error and credential exfiltration vulnerability affecting Kaniko prior to version 1.25.20. The flaw stems from an unanchored regular expression in the integrated Azure Container Registry (ACR) credential helper (github.com/chrismellard/docker-credential-acr-env). When Kaniko processes a Dockerfile containing an image reference hosted on a lookalike domain containing an ACR suffix as a substring (e.g., x.azurecr.io.attacker.com), the credential helper acquires a Microsoft Entra ID access token for Azure Resource Manager and transmits it via HTTP POST to the attacker-controlled host.

Amit Schendel
Amit Schendel
5 views•11 min read
•about 4 hours ago•CVE-2026-62300
6.5

CVE-2026-62300: Uncontrolled Resource Consumption in filecoin-pin Daemon

CVE-2026-62300 is an uncontrolled resource consumption vulnerability (CWE-400) affecting the daemon mode of filecoin-pin in versions up to and including 1.1.0. The daemon implements the IPFS Pinning Service API to store content on Filecoin's Proof of Data Possession (PDP) service. Due to the absence of rate limits, concurrency caps, execution timeouts, and Directed Acyclic Graph (DAG) traversal limits, an authenticated user—or an unauthenticated user when authentication is disabled—can exhaust system resources via crafted POST /pins requests.

Amit Schendel
Amit Schendel
5 views•11 min read
•about 5 hours ago•CVE-2026-61536
7.5

CVE-2026-61536: Remote Code Execution via Unsafe Reflection in masci/banks CompletionExtension

CVE-2026-61536 is a high-severity Remote Code Execution (RCE) vulnerability in the masci/banks Python library prior to version 2.4.3. The flaw exists within the CompletionExtension component, which parses JSON-serialized Tool definitions directly from rendered Jinja template bodies inside {% completion %} blocks. When handling tool calls returned by an LLM, the library dynamically resolves the target callable using importlib.import_module() and getattr() based on an unvalidated import_path string. An attacker who can supply or modify prompt templates can inject a malicious Tool JSON object pointing to arbitrary Python functions (such as os.system), bypassing the Jinja SandboxedEnvironment introduced in version 2.4.2 and achieving arbitrary code execution when the LLM invokes the tool.

Alon Barad
Alon Barad
6 views•10 min read
•1 day ago•CVE-2026-93363
4.3

CVE-2026-93363: Improper Access Control in Payload CMS Storage Upload Route

Payload CMS contains a missing authorization vulnerability (CWE-862) in its client-side upload instructions endpoint and the `@payloadcms/storage-vercel-blob` storage adapter. Two distinct logic defects allow authenticated users lacking collection-level `create` or `update` permissions to generate signed upload tokens and upload arbitrary files directly to external cloud storage.

Alon Barad
Alon Barad
7 views•9 min read
•1 day ago•CVE-2026-55098
6.5

CVE-2026-55098: Cross-Database Authorization Bypass via DuckDB Table-Valued I/O Functions in Basekick-Labs Arc

CVE-2026-55098 (GHSA-93cm-2v4m-c56c) is an authorization bypass and sensitive information disclosure vulnerability in Basekick-Labs Arc prior to version 26.06.2. The flaw stems from an incomplete remediation of CVE-2026-47735, which failed to restrict the full suite of DuckDB table-valued filesystem I/O functions and quoted-identifier invocations. Because Arc's query parser ignores function calls during table reference extraction, authenticated users with minimal or empty permissions can invoke functions like parquet_scan(), glob(), and read_blob() to read, enumerate, and extract telemetry data across all tenant databases residing within the shared local storage root.

Alon Barad
Alon Barad
7 views•10 min read
•1 day ago•CVE-2026-113787
6.1

CVE-2026-113787: Stored Cross-Site Scripting via Unescaped Style Attributes in odf-kit

CVE-2026-113787 is a stored Cross-Site Scripting (XSS) and HTML injection vulnerability affecting the odf-kit npm package from version 0.6.0 prior to 0.14.2. The HTML conversion engines (odtToHtml and odsToHtml) interpolate document-controlled styling and image attributes directly into inline style and src attributes without escaping double-quote characters. A remote attacker can supply a crafted .odt or .ods document to break out of HTML attribute boundaries and execute arbitrary JavaScript in the context of any web application rendering the converted HTML.

Alon Barad
Alon Barad
7 views•11 min read