mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 14:11:31 +00:00
fix(server): SEC-003 — keep securityHeadersMiddleware in rate-limit stack
Sprint 1 unified-master-audit closure. cmd/server/main.go built two
middleware stacks: a default (line ~2054) and a rate-limit-enabled
rebuild (line ~2079). The rebuild dropped securityHeadersMiddleware,
silently turning off five browser-side defenses (Strict-Transport-
Security, X-Frame-Options, X-Content-Type-Options, Referrer-Policy,
Content-Security-Policy) the moment an operator flipped
CERTCTL_RATE_LIMIT_ENABLED=true.
Fix: re-insert securityHeadersMiddleware at the same position as the
default stack and place rateLimiter immediately after, so even a 429
response carries the same headers as a 200.
Regression coverage:
- cmd/server/main_test.go TestMain_RateLimitedStack_EmitsSecurityHeaders
mirrors the production stack composition and asserts each of the
five headers lands on the response. A future regression that
removes securityHeadersMiddleware (or reorders it after the rate
limiter such that a 429 misses the headers) surfaces here.
Closes SEC-003.
This commit is contained in:
@@ -2076,11 +2076,22 @@ func main() {
|
||||
PerUserRPS: cfg.RateLimit.PerUserRPS,
|
||||
PerUserBurstSize: cfg.RateLimit.PerUserBurstSize,
|
||||
})
|
||||
// SEC-003 closure (Sprint 1, 2026-05-16). Pre-fix the
|
||||
// rate-limit-enabled stack was rebuilt without
|
||||
// securityHeadersMiddleware, silently dropping HSTS,
|
||||
// X-Frame-Options, X-Content-Type-Options, Referrer-Policy,
|
||||
// and Content-Security-Policy across every response when an
|
||||
// operator flipped CERTCTL_RATE_LIMIT_ENABLED=true — a
|
||||
// defensive-config toggle weakened browser-side security.
|
||||
// The fixed stack keeps securityHeadersMiddleware at the same
|
||||
// position as the default and inserts rateLimiter right after
|
||||
// so a 429 response still carries the same headers as a 200.
|
||||
middlewareStack = []func(http.Handler) http.Handler{
|
||||
middleware.RequestID,
|
||||
structuredLogger,
|
||||
middleware.Recovery,
|
||||
bodyLimitMiddleware,
|
||||
securityHeadersMiddleware,
|
||||
rateLimiter,
|
||||
corsMiddleware,
|
||||
// Phase 6 chain: Auth (session-then-Bearer fallback) → CSRF
|
||||
|
||||
Reference in New Issue
Block a user