diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..804c842 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2025-02-28 - Missing Write Deadline for HTTP Server Handlers +**Vulnerability:** The HTTP server handlers, including CORS preflight handling, missed an explicit write deadline for standard responses, potentially causing the server to hang or consume resources against a slow reader (slowloris-style attack). Only delayed responses had a write deadline configured previously. +**Learning:** `http.Server` configured with `ReadTimeout` does not apply to writing the response. Unless `WriteTimeout` is configured at the server level, or `SetWriteDeadline` is set explicitly on the ResponseController/connection per request, the handlers can block indefinitely when trying to send data to slow clients. +**Prevention:** Always ensure an explicit write deadline using `http.NewResponseController(w).SetWriteDeadline(...)` for every request before calling `w.Write`, or set a server-level `WriteTimeout`. diff --git a/internal/server/server.go b/internal/server/server.go index 5883929..170f054 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -117,6 +117,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { }) if s.opts.CORS && isPreflight(r) { + _ = http.NewResponseController(w).SetWriteDeadline(time.Now().Add(30 * time.Second)) resp := events.Response{Status: http.StatusNoContent, Headers: corsHeaders(r, true)} write(w, resp) s.store.Complete(id, resp, time.Since(start)) @@ -124,8 +125,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { } resp := s.resp.Render() + _ = http.NewResponseController(w).SetWriteDeadline(time.Now().Add(resp.Delay + 30*time.Second)) if resp.Delay > 0 { - _ = http.NewResponseController(w).SetWriteDeadline(time.Now().Add(resp.Delay + 30*time.Second)) timer := time.NewTimer(resp.Delay) defer timer.Stop() select {