GHSA-m98w-cqp3-qcqr
Fiber Utils UUIDv4 and UUID Silent Fallback to Predictable Values
EPSS Exploitation Probability
EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.
Blast Radius
github.com/gofiber/utils/v2🐹github.com/gofiber/utilsReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.
Description
Summary
Critical security vulnerabilities exist in both the UUIDv4() and UUID() functions of the github.com/gofiber/utils package. When the system's cryptographic random number generator (crypto/rand) fails, both functions silently fall back to returning predictable UUID values, the zero UUID "00000000-0000-0000-0000-000000000000". This compromises the security of all Fiber applications using these functions for security-critical operations on Go versions prior to 1.24.
Both functions are vulnerable to the same root cause (crypto/rand failure):
UUIDv4(): Indirect vulnerability throughuuid.NewRandom()→crypto/rand.Read()→ fallback toUUID()UUID(): Direct vulnerability throughcrypto/rand.Read(uuidSeed[:])→ silent zero UUID return
Note: Go 1.24 and later panics on
crypto/randRead()failures, mitigating this vulnerability. Applications running on Go 1.24+ are not affected by the silent fallback behavior.
Vulnerability Details
Affected Functions
- Package:
github.com/gofiber/utils - Functions:
UUIDv4()andUUID() - Return Type:
string(both functions) - Locations:
common.go:93-99(UUIDv4),common.go:60-89(UUID)
Technical Description
The vulnerability occurs through two related but distinct failure paths, both ultimately caused by crypto/rand.Read() failures on Go < 1.24:
Primary Path: UUIDv4() Vulnerability
UUIDv4()callsgoogle/uuid.NewRandom()which internally usescrypto/rand.Read()- If
uuid.NewRandom()fails,UUIDv4()falls back to the internalUUID()function - No error is returned to the application - silent security failure occurs
Secondary Path: UUID() Vulnerability
UUID()directly callscrypto/rand.Read(uuidSeed[:])to seed its internal state- If seeding fails,
UUID()silently fails and returns the zero UUID"00000000-0000-0000-0000-000000000000" - Applications receive predictable UUIDs with no indication of the security failure
Code Analysis
UUIDv4() Vulnerability Path
func UUIDv4() string {
token, err := uuid.NewRandom() // Uses crypto/rand.Read() internally
if err != nil {
return UUID() // Dangerous fallback - no error returned to application
}
return token.String()
}
UUID() Vulnerability Path
func UUID() string {
uuidSetup.Do(func() {
if _, err := rand.Read(uuidSeed[:]); err != nil { // Direct crypto/rand.Read() call
return // Silent failure - no seeding, uuidCounter remains 0
}
uuidCounter = binary.LittleEndian.Uint64(uuidSeed[:8])
})
if atomic.LoadUint64(&uuidCounter) <= 0 {
return "00000000-0000-0000-0000-000000000000" // Zero UUID returned silently
}
// ... generate UUID from counter
}
Root Cause: Both vulnerabilities stem from crypto/rand.Read() failures, occurring through different code paths with the same dangerous silent fallback behavior.
Security Impact
Severity: CRITICAL
This issue is especially severe because many Fiber middleware packages (session, CSRF, auth, rate-limit, request-ID, etc.) default to utils.UUIDv4() for generating security-sensitive identifiers. A failure in crypto/rand would cause every generated identifier across the entire application to collapse to a single predictable value (the zero UUID), resulting in:
- Session fixation / universal session hijack
- CSRF token predictability and bypass
- Authentication token replay
- Global identifier collisions leading to severe application breakage
- Potential application-wide DoS due to every request using the same “unique” key, causing cache overwrites, session stomping, corrupted internal maps, and loss of isolation across all users
Attack Scenario
While entropy exhaustion is extremely rare on modern Linux systems, RNG access failures (e.g., restricted /dev/random or /dev/urandom access, broken container environments, sandbox restrictions, misconfigured VMs, or FIPS-mode RNG failures) are realistic. In these scenarios on Go < 1.24, crypto/rand may return errors immediately — triggering the vulnerable fallback paths.
On Go 1.24+, crypto/rand Read() panics on failure, mitigating the silent-zero fallback issue.
Proof of Concept
uuid.NewRandom()fails (indirectcrypto/rand.Read()failure)UUIDv4()callsUUID()as fallback with no error returnedUUID()seeding fails directly viacrypto/rand.Read(uuidSeed[:])- Zero UUID
"00000000-0000-0000-0000-000000000000"is returned silently - No error is propagated to the application from either function
Affected Versions
- All versions of
github.com/gofiber/utilscontaining theUUIDv4()orUUID()functions - Applications using Fiber middleware that depend on
UUIDv4()orUUIDfor security - Only applicable to Go < 1.24; Go 1.24+ panics/block on
crypto/randRead()failures and is not affected
Mitigation
Immediate Workaround
Replace usage of utils.UUIDv4() with uuid.New() or wait for fix:
sessionID := uuid.New()
Recommended Fix
Modify utils.UUIDv4() and utils.UUID() to fail explicitly when cryptographic randomness is unavailable:
func UUIDv4() string {
token, err := uuid.NewRandom()
if err != nil {
panic(fmt.Sprintf("utils: failed to generate secure UUID: %v", err))
}
return token.String()
}
func UUID() string {
uuidSetup.Do(func() {
if _, err := rand.Read(uuidSeed[:]); err != nil {
panic(fmt.Sprintf("utils: failed to seed UUID generator: %v", err))
}
uuidCounter = binary.LittleEndian.Uint64(uuidSeed[:8])
})
if atomic.LoadUint64(&uuidCounter) <= 0 {
panic("utils: UUID generator not properly seeded")
}
// ... generate UUID from counter
}
Detection
Applications can detect if they're affected by:
- Checking if they use
github.com/gofiber/utils - Searching for
UUIDv4()andUUID()usage in security-critical code paths - Reviewing Fiber middleware configurations that rely on defaults of
UUIDv4()for security identifiers
References
- Package Repository: https://github.com/gofiber/utils
- Fiber Framework: https://github.com/gofiber/fiber
- Google UUID Library: https://github.com/google/uuid
- Golang
crypto/randbehavior changes: golang/go#66821, Go 1.25.5 source
Contact
Reported by: @sixcolors
Classification
- OWASP: A02:2021 - Cryptographic Failures
- Impact: Complete compromise of application security model on Go < 1.24
- Exploitability: Medium (requires entropy failure)
- Scope: All Fiber applications using affected middleware on Go < 1.24
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐹Go | github.com/gofiber/utils/v2 | all versions | 2.0.0-rc.4 |
| 🐹Go | github.com/gofiber/utils | all versions | 1.2.0 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/gofiber/utils/v2. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.
Fix
Update github.com/gofiber/utils/v2 to 2.0.0-rc.4 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-m98w-cqp3-qcqr is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 pinpoints whether GHSA-m98w-cqp3-qcqr is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.
Tailored to GHSA-m98w-cqp3-qcqr. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is GHSA-m98w-cqp3-qcqr in your dependencies?
O3 detects GHSA-m98w-cqp3-qcqr across Go dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.