Predictable secret ID and lack of secret origin API enable confused deputy attacks on Juju workloads.
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:
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
This allows for an IDOR attack where:
Evil could benefit by:
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.
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)
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:
(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:
{
"cwe_ids": [
"CWE-343"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-19T17:43:47Z",
"nvd_published_at": "2026-03-18T14:16:40Z",
"severity": "MODERATE"
}