diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 000000000..0bb5d19ab --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2025-02-28 - [Medium] Fix Missing HTTP Server Timeouts +**Vulnerability:** Go's standard `http.ListenAndServe` and unconfigured `http.Server` instances lack default timeouts for reading headers, reading bodies, and writing responses. +**Learning:** These default settings leave the application vulnerable to resource exhaustion and Denial of Service (DoS) attacks, such as Slowloris, because malicious clients can slowly send data and tie up server connections indefinitely. +**Prevention:** Always instantiate `http.Server` explicitly and set `ReadHeaderTimeout`, `ReadTimeout`, `WriteTimeout`, and (optionally) `IdleTimeout` to reasonable values based on the expected request sizes and latencies. diff --git a/pkg/auth/oauth.go b/pkg/auth/oauth.go index 4667e3d81..2ba75b0c5 100644 --- a/pkg/auth/oauth.go +++ b/pkg/auth/oauth.go @@ -118,7 +118,12 @@ func LoginBrowser(cfg OAuthProviderConfig) (*AuthCredential, error) { return nil, fmt.Errorf("starting callback server on port %d: %w", cfg.Port, err) } - server := &http.Server{Handler: mux} + server := &http.Server{ + Handler: mux, + ReadTimeout: 10 * time.Second, + ReadHeaderTimeout: 5 * time.Second, + WriteTimeout: 10 * time.Second, + } go server.Serve(listener) defer func() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) diff --git a/pkg/channels/manager.go b/pkg/channels/manager.go index 051dec6ed..c163cbce3 100644 --- a/pkg/channels/manager.go +++ b/pkg/channels/manager.go @@ -344,10 +344,11 @@ func (m *Manager) SetupHTTPServer(addr string, healthServer *health.Server) { } m.httpServer = &http.Server{ - Addr: addr, - Handler: m.mux, - ReadTimeout: 30 * time.Second, - WriteTimeout: 30 * time.Second, + Addr: addr, + Handler: m.mux, + ReadTimeout: 30 * time.Second, + ReadHeaderTimeout: 10 * time.Second, + WriteTimeout: 30 * time.Second, } } diff --git a/pkg/health/server.go b/pkg/health/server.go index 5609ebdf6..a3f6e4df2 100644 --- a/pkg/health/server.go +++ b/pkg/health/server.go @@ -44,10 +44,11 @@ func NewServer(host string, port int) *Server { addr := fmt.Sprintf("%s:%d", host, port) s.server = &http.Server{ - Addr: addr, - Handler: mux, - ReadTimeout: 5 * time.Second, - WriteTimeout: 5 * time.Second, + Addr: addr, + Handler: mux, + ReadTimeout: 5 * time.Second, + ReadHeaderTimeout: 3 * time.Second, + WriteTimeout: 5 * time.Second, } return s diff --git a/web/backend/main.go b/web/backend/main.go index 7a575cc47..ee88e7fd0 100644 --- a/web/backend/main.go +++ b/web/backend/main.go @@ -163,7 +163,16 @@ func main() { }() // Start the Server - if err := http.ListenAndServe(addr, handler); err != nil { + server := &http.Server{ + Addr: addr, + Handler: handler, + ReadTimeout: 10 * time.Second, + ReadHeaderTimeout: 5 * time.Second, + WriteTimeout: 30 * time.Second, + IdleTimeout: 120 * time.Second, + } + + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("Server failed to start: %v", err) } }