Mar 19, 2026·6 min read·2 visits
A predictable ID generation algorithm combined with a lack of provenance checks allows malicious Juju applications to steal secrets from other applications via a Confused Deputy attack.
Canonical Juju versions 3.0.0 through 3.6.18 contain a critical authorization bypass vulnerability within the secret management subsystem. Due to predictable secret identifiers and the absence of provenance verification, a malicious application can leverage a provider application as a confused deputy to access secrets belonging to other applications in the same model.
Canonical Juju versions 3.0.0 through 3.6.18 contain an authorization bypass vulnerability in the secret management subsystem. Tracked as CVE-2026-32694, this flaw manifests as an Insecure Direct Object Reference (IDOR) coupled with a Confused Deputy condition. The vulnerability enables a malicious application within a shared Juju model to inappropriately access or manipulate secrets owned by other applications.
The Juju architecture relies on relations to share configuration and state between deployed applications. The secret management subsystem issues identifiers for sensitive data, which are subsequently passed between providing and consuming applications via these relations. Prior to version 3.6.19, the generation algorithm for these identifiers produced predictable values.
Furthermore, the API lacked a secure mechanism for downstream applications to verify the provenance of a received secret identifier. This missing validation step creates the Confused Deputy scenario. A malicious application can provide a predicted identifier to a privileged provider application, tricking it into executing operations against a victim's secrets.
The root cause of CVE-2026-32694 involves two distinct architectural shortcomings. The primary flaw resides in the predictable nature of the XIDs (Globally Unique Process-ID-first Identifiers) used to track secret objects. Juju generated these XIDs using a structured format comprising a 4-byte timestamp, a 3-byte machine identifier, a 2-byte process ID (PID), and a 3-byte counter.
Within a shared environment, such as a single Juju controller managing a Kubernetes model, several of these XID components remain static or highly predictable. The machine ID and PID rarely change across sequential operations. An attacker observing the creation of their own secrets can accurately determine the current timestamp and counter values, allowing them to extrapolate the precise XIDs generated for other applications.
The secondary flaw is a lack of provenance verification, manifesting as a Confused Deputy condition. The Juju API permits "Provider" applications to hold access rights to secrets owned by multiple different "Grantee" applications. When a Provider receives a secret ID over a relation, the API historically provided no method to confirm which application actually owned that secret.
Because the Provider lacks context regarding the secret's true origin, it operates under the assumption that the secret belongs to the remote end of the relation supplying the ID. If the Provider possesses valid access grants for a victim's secret, it will blindly execute requested operations on behalf of the attacker supplying the predicted ID.
The remediation requires fundamental changes to how Juju resolves remote applications and issues backend tokens. The patch at commit 7875461e90ced257835077cedaa60454bffb44d1 addresses the inability to accurately resolve remote units to their parent remote applications during secret operations.
The vulnerable implementation of findSecretEntity failed to handle cases where a unit belonged to a remote application in Cross-Model Relations (CMR). The patch introduces error handling to catch errors.IsNotFound(err) when querying a unit, falling back to resolving the remote application identity.
// Patched findSecretEntity logic in state/secrets.go
case names.UnitTag:
entity, err = st.Unit(id)
- collName = unitsC
- docID = id
+ if err == nil {
+ docID = id
+ collName = unitsC
+ } else if errors.IsNotFound(err) {
+ // If this unit is from a remote application, find that instead.
+ id, err = names.UnitApplication(id)
+ if err != nil {
+ return nil, "", "", err
+ }
+ entity, err = st.RemoteApplication(id)
+ docID = id
+ collName = remoteApplicationsC
+ }Additionally, commit 12eeffe70ee606f34802f7f1442f672bcbd9d70b implements robust backend tokens. Alongside switching from sequential XIDs to 128-bit random nonces for secret IDs, Juju introduced the secret-info-get tool. This API addition allows deputies to explicitly verify the owner and grant-relation-id metadata, breaking the Confused Deputy attack chain.
Exploitation of CVE-2026-32694 requires an attacker to control at least one application deployed within the target Juju model. The attacker must share a model with a targeted "Good" application and a common "Provider" application, such as a centralized database or proxy charm. The attacker must also be capable of establishing a relation with the Provider.
The attack sequence begins with the attacker creating several secrets to sample the current XID generation state. By analyzing the returned XIDs, the attacker extracts the static machine ID and PID, and maps the current timestamp and counter values. The attacker then calculates the likely XID of a secret recently generated by the target application.
The attacker transmits this predicted XID to the Provider application via their shared relation data. The Provider attempts to retrieve the secret using the supplied ID. Because the Provider holds a valid grant to the victim's secret, the Juju controller permits the read operation. The Provider then proceeds to use or expose the victim's secret data based on the attacker's inputs.
The successful exploitation of CVE-2026-32694 yields a severe breach of confidentiality and integrity within the impacted Juju model. An attacker successfully bypassing the authorization controls gains unauthorized access to sensitive material such as database credentials, API keys, and cryptographic certificates belonging to other applications.
While the CVSS score is 6.6 (Medium) due to the high attack complexity and high privileges required, the localized impact on a multi-tenant or shared-resource model is substantial. The attacker must already possess valid application deployment rights within the model, which limits the threat to insider risks or scenarios where a single application has been compromised.
The vulnerability does not directly expose the Juju controller itself to remote code execution. However, the lateral movement capabilities provided by accessing adjacent application credentials facilitate broader compromise of the infrastructure managed by the Juju model.
Canonical addressed CVE-2026-32694 in Juju version 3.6.19. The patch eliminates the IDOR vulnerability by replacing predictable XIDs with 128-bit random nonces. This cryptographic entropy ensures that secret identifiers cannot be calculated or guessed, regardless of the attacker's visibility into the model's activity.
To remediate the Confused Deputy vector, Juju 3.6.19 introduces the secret-info-get hook tool. Charm developers must update their provider charms to utilize this new API. Provider applications are now required to query the provenance of any secret ID received via relation data and verify that the owner matches the expected remote application.
Administrators must upgrade all Juju controllers and agents to version 3.6.19 or later. Following the upgrade, operators must systematically rotate all existing secrets within shared models. Legacy secrets generated prior to the upgrade retain their predictable XIDs and remain theoretically vulnerable until they are replaced with the new, high-entropy identifiers.
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Juju Canonical | >= 3.0.0, <= 3.6.18 | 3.6.19 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-639, CWE-343 |
| Attack Vector | Network |
| Privileges Required | High |
| CVSS v3.1 | 6.6 |
| Exploit Status | Proof-of-Concept |
The system's authorization mechanism does not adequately verify that the user requesting access to a specific object is authorized to do so.