Skip to content

fix: low-severity security hardening across all modules#6

Merged
ConsoleTVs merged 13 commits into
mainfrom
fix/low-security-vulnerabilities
Apr 11, 2026
Merged

fix: low-severity security hardening across all modules#6
ConsoleTVs merged 13 commits into
mainfrom
fix/low-security-vulnerabilities

Conversation

@ConsoleTVs
Copy link
Copy Markdown
Member

Summary

Addresses all 20 LOW-severity findings (#33-#52) from the security audit.

Security Hardening

  • Session IDs: Replaced UUID v7 with crypto/rand + base64url (256-bit entropy, no timestamp leakage) — removes google/uuid dependency
  • Session ID validation: Reject malformed session IDs before cache lookup to prevent key injection
  • Session defaults: MiddlewareWith() zero-value options now default to Secure=true, SameSite=Lax, sensible TTL/cookie settings via withDefaults()
  • Bcrypt cost: Raised default from 10 to 12 (OWASP) with minimum cost enforcement
  • Password zeroing: defer zeroBytes(value) in all Hash/Check methods (Argon2 + Bcrypt)
  • Encryption AAD: Optional AdditionalData field on AES and ChaCha20 for context binding
  • Key zeroing: Close() method on AES and ChaCha20 to zero key material from memory
  • AES cipher caching: GCM instance created once at construction, not per-call
  • Cache key privacy: Removed cache keys from error messages to prevent enumeration
  • HTML charset: Added charset=utf-8 to HTML Content-Type to prevent charset-sniffing XSS
  • Default Content-Type: Raw() and Stream() now set application/octet-stream when unset
  • Problem Instance: Uses r.URL.Path only (strips query string)

Resilience

  • AfterResponse hooks: Panics in hooks are now recovered and logged via slog
  • MemoryBroker: Recovered panics are logged instead of silently swallowed
  • AMQP subscriber: Removed redundant wg.Done() preventing double-decrement panic
  • MQTT unsubscribe: Uses context.WithoutCancel(ctx) to avoid expired-context failures

New APIs

  • ParamInt(), ParamIntOr(), QueryInt(), QueryIntOr() — typed integer parsing helpers in contract/request/
  • sql.Configure(func(*sql.DB)) — exposes connection pool tuning
  • AES.Close(), ChaCha20.Close() — key material zeroing

Documentation

  • WARNING docs on broker credential storage (NATS, MQTT, AMQP)
  • WARNING docs on log injection mitigation in Logger middleware
  • WARNING docs on path.Join normalization in router Group()
  • Catch-all route base-path matching documented
  • Connection pool best practices documented

Testing

All 4 modules pass go vet and go test:

  • contract, router, problem, framework

Files Changed

25 files across all 4 modules (577 additions, 161 deletions)

UUID v7 embeds a creation timestamp and provides only 74 bits of
entropy. Replace with 32 bytes from crypto/rand encoded as base64url,
yielding 256 bits of pure entropy with no timestamp leakage.

This also removes the github.com/google/uuid dependency.
Add withDefaults() method on MiddlewareOptions that sets secure
defaults when fields are zero-valued: Secure=true, SameSite=Lax,
Path="/", Name=DefaultCookie, Key=contract.SessionKey,
TTL=DefaultTTL, ExpirationDelta=DefaultExpirationDelta.

Called at the start of MiddlewareWith() so callers get safe defaults
for unset fields while still being able to override specific ones.
… to Raw/Stream

Set Content-Type to text/html; charset=utf-8 for HTML and HTMLTemplate
to prevent XSS via charset sniffing in older browsers. Add
application/octet-stream as default Content-Type for Raw() and Stream()
when no Content-Type has been explicitly set on the response writer.
Add ParamInt, ParamIntOr, QueryInt, and QueryIntOr helpers that parse
and validate numeric parameters using only stdlib strconv. This prevents
injection via malformed numeric params by returning clear errors for
non-integer values.
… matching

Add WARNING doc comments to Group() and Method() explaining that
path.Join normalizes .. segments in route patterns. Document that
catch-all routes (e.g., /files/{path...}) also match their base path
and handlers should account for empty catch-all values.
- Raise default bcrypt cost from 10 to 12 per OWASP recommendation
- Enforce minimum cost of bcrypt.MinCost (4) in NewBcryptWith()
- Zero password bytes from memory after Hash/Check in both Bcrypt
  and Argon2 via defer zeroBytes() to limit exposure window
- Update tests to use separate byte slices for Hash and Check since
  the password slice is now zeroed after each call
…eration

Return the sentinel error directly without appending the key value.
This prevents potential cache key enumeration attacks through error
messages while preserving the ability to match errors with errors.Is.
- Add optional AdditionalData field to AES and ChaCha20 structs for
  binding ciphertext to a context (user ID, resource path) via AAD
- Pass AdditionalData to Seal/Open calls in both Encrypt and Decrypt
- Add Close() method to both AES and ChaCha20 that zeros key material
  from memory; callers should defer Close after construction
- Store raw key in ChaCha20 struct so Close can zero it
The deliverToHandler method had an empty recover block that silently
swallowed panics. Now logs recovered values via slog.Error so panicking
event handlers are visible for debugging.
Add Configure method on *SQL that accepts a func(*sql.DB) callback,
allowing callers to set pool parameters like SetMaxOpenConns,
SetMaxIdleConns, and SetConnMaxLifetime without importing database/sql.
Wrap each AfterResponse callback invocation with panic recovery and
slog.Error logging. This prevents a single panicking hook from crashing
the server and ensures remaining hooks still execute.
Add security note explaining that slog structured logging mitigates
classic log injection attacks by emitting values as discrete key-value
pairs. Warn that callers forwarding logs to plain-text renderers should
remain aware that attacker-controlled URLs appear in log entries.
…erabilities

# Conflicts:
#	contract/request/param.go
#	contract/request/query.go
#	contract/response/static.go
#	framework/event/memory.go
#	framework/session/middleware.go
#	framework/session/session.go
@ConsoleTVs ConsoleTVs merged commit b126e09 into main Apr 11, 2026
2 checks passed
@ConsoleTVs ConsoleTVs deleted the fix/low-security-vulnerabilities branch April 11, 2026 00:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant