Skip to content

PoP Authentication Security Fixes

SEC-0001: PoP Authentication Security Fixes

Date Author Severity
2026-02-26 Fabian Beyerlein see individual issues

Issues Fixed

1. Parser Input Validation (HIGH)

Problem: ParsePoP() accepted unbounded input, enabling DoS attacks

  • No size limits on header or individual fields
  • No format validation (UUID, base64)
  • Silent handling of malformed data

Fix:

  • Added max lengths: header 1KB, kid/nonce 128B, signature 512B
  • UUID validation for kid and nonce fields
  • Base64 validation for signature
  • Timestamp bounds checking (0 to year 9999)
  • Duplicate field detection
  • Returns specific errors for each validation failure

Files:

  • backend/pkg/pop/pop.go
  • backend/pkg/pop/pop_test.go (unit tests)

Verification:

go test -fuzz=FuzzParsePoP -fuzztime=5m ./backend/pkg/pop
# Result: 53M+ iterations, 0 crashes, 220 interesting inputs

2. Nonce Replay Race Condition (CRITICAL)

Problem: Check-then-store pattern allowed replay attacks under concurrent load

// Old code - race window:
if cache.Exists(nonce) { return error }
cache.Store(nonce)  // ← Two requests can both pass

Fix: Atomic StoreIfNotExists() operation

// New code - atomic:
stored, err := cache.StoreIfNotExists(nonce, ttl)
if !stored { return "replay detected" }

Files:

  • backend/apps/nexus/modules/adapter/domain/cache.go (interface)
  • backend/apps/nexus/modules/adapter/infra/redis_nonce_cache.go (Redis SETNX)
  • backend/apps/nexus/modules/adapter/app/adapter_auth.go (usage)

3. Redis TTL Bug (MEDIUM)

Problem: Hardcoded 15min TTL instead of using configurable parameter

  • Replay window 3x larger than intended
  • Security policy not enforced

Fix: Use ttl parameter in Redis SET command

// Old: c.redisClient.Set(ctx, key, "1", 15*time.Minute)
// New: c.redisClient.Set(ctx, key, "1", ttl)

Files:

  • backend/apps/nexus/modules/adapter/infra/redis_nonce_cache.go

4. Silent Cache Failure (MEDIUM)

Problem: Authentication continued even if nonce storage failed

  • Defeats replay protection on cache errors
  • Fail-open security vulnerability

Fix: Return error if nonce cannot be stored

stored, err := cache.StoreIfNotExists(...)
if err != nil {
    return errors.New("nonce validation failed")
}

Files:

  • backend/apps/nexus/modules/adapter/app/adapter_auth.go