security: add HTTP server timeouts, graceful shutdown, and security headers (#11, #12, #13)#588
Merged
lakhansamani merged 1 commit intomainfrom Apr 7, 2026
Merged
Conversation
…eaders (#11, #12, #13) #11 — No HTTP server timeouts (slowloris) The main HTTP server used router.Run() which constructs an http.Server with no Read/Write/Idle timeouts. A slow client could hold a connection open indefinitely sending headers one byte at a time. Fix: build *http.Server explicitly with: - ReadHeaderTimeout: 10s (the slowloris defence — bounds time to receive request headers) - ReadTimeout: 30s - WriteTimeout: 60s - IdleTimeout: 120s - MaxHeaderBytes: 1 MB The metrics server gets the same hardening. #12 — No graceful shutdown for the main HTTP server The metrics server already had a Shutdown call wired to context cancellation but the main HTTP server was killed mid-flight when the process received a signal, dropping in-progress responses. Fix: shut down BOTH servers with srv.Shutdown(ctx) on context cancellation, with a 30-second drain timeout. #13 — Missing security headers SecurityHeadersMiddleware only set X-Content-Type-Options, X-Frame-Options, Referrer-Policy, and X-XSS-Protection. Missing HSTS, CSP, Permissions-Policy. Token responses had no Cache-Control. Fix: - Permissions-Policy disabling geolocation/microphone/camera/payment/usb - Strict-Transport-Security gated behind a new --enable-hsts flag (default off — operators not behind TLS would lock browsers out for a year) - Content-Security-Policy on by default with a conservative starting policy (frame-ancestors 'none' replaces X-Frame-Options as the modern equivalent) and a --disable-csp escape hatch for dashboards we haven't tightened yet - /oauth/token responses now set Cache-Control: no-store, no-cache, must-revalidate, private (RFC 6749 §5.1) and Pragma: no-cache
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three HTTP-server hardenings:
#11 — No HTTP server timeouts (slowloris)
The main HTTP server used
router.Run()which constructs anhttp.Serverwith no Read/Write/Idle timeouts. A slow client could hold a connection open indefinitely sending headers one byte at a time.#12 — No graceful shutdown for the main HTTP server
The metrics server already had a
Shutdowncall wired to context cancellation but the main HTTP server was killed mid-flight when the process received a signal, dropping in-progress responses.#13 — Missing security headers
The middleware only set X-Content-Type-Options, X-Frame-Options, Referrer-Policy, X-XSS-Protection. Missing HSTS, CSP, Permissions-Policy. Token responses had no
Cache-Control.Changes
*http.Serverexplicitly for both the main HTTP and metrics servers withReadHeaderTimeout: 10s,ReadTimeout: 30s,WriteTimeout: 60s,IdleTimeout: 120s,MaxHeaderBytes: 1 MiB.srv.Shutdown(ctx)with a 30s drain timeout when the process context is cancelled.--enable-hsts, default-on CSP with conservative policy and--disable-cspescape hatch./oauth/tokenresponses now setCache-Control: no-store, no-cache, must-revalidate, privateandPragma: no-cacheper RFC 6749 §5.1.Test plan
go build ./...TEST_DBS=sqlite go test -run TestSignup ./internal/integration_tests/