From 8f07a434a38dc993279cc692a0e077a2d34a6845 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 15 Mar 2026 17:09:15 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[MEDIUM]=20?= =?UTF-8?q?Fix=20missing=20HTTP=20client=20timeouts=20in=20OAuth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced uses of standard `http.Post` and `http.PostForm` (which use the default `http.Client` with no timeout) in `pkg/auth/oauth.go` with an explicitly instantiated `http.Client` that includes a 15-second timeout. This prevents the application from hanging indefinitely or exhausting resources if an external OAuth service is slow or unresponsive. Also updated `.jules/sentinel.md` with this security learning. Co-authored-by: hobbyistlabs-coder <267281733+hobbyistlabs-coder@users.noreply.github.com> --- .jules/sentinel.md | 5 +++++ pkg/auth/oauth.go | 15 ++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 0bb5d19ab..ef1bfd604 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -2,3 +2,8 @@ **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. + +## 2025-02-28 - [MEDIUM] Fix missing HTTP client timeouts in OAuth +**Vulnerability:** Go's standard `http.Post`, `http.PostForm`, `http.Get`, and the default `http.Client` do not have timeouts configured by default. +**Learning:** These defaults can leave the application vulnerable to resource exhaustion or indefinite hangs if the external service (like an OAuth provider) is slow, unresponsive, or experiencing an outage. +**Prevention:** Always instantiate `http.Client` explicitly with a sensible `Timeout` (e.g., `Timeout: 15 * time.Second`) before making outbound HTTP requests, instead of using the default package-level convenience functions. diff --git a/pkg/auth/oauth.go b/pkg/auth/oauth.go index d503d1721..be4f5528b 100644 --- a/pkg/auth/oauth.go +++ b/pkg/auth/oauth.go @@ -208,7 +208,8 @@ func RequestDeviceCode(cfg OAuthProviderConfig) (*DeviceCodeInfo, error) { "client_id": cfg.ClientID, }) - resp, err := http.Post( + client := &http.Client{Timeout: 15 * time.Second} + resp, err := client.Post( cfg.Issuer+"/api/accounts/deviceauth/usercode", "application/json", strings.NewReader(string(reqBody)), @@ -299,7 +300,8 @@ func LoginDeviceCode(cfg OAuthProviderConfig) (*AuthCredential, error) { "client_id": cfg.ClientID, }) - resp, err := http.Post( + client := &http.Client{Timeout: 15 * time.Second} + resp, err := client.Post( cfg.Issuer+"/api/accounts/deviceauth/usercode", "application/json", strings.NewReader(string(reqBody)), @@ -358,7 +360,8 @@ func pollDeviceCode(cfg OAuthProviderConfig, deviceAuthID, userCode string) (*Au "user_code": userCode, }) - resp, err := http.Post( + client := &http.Client{Timeout: 15 * time.Second} + resp, err := client.Post( cfg.Issuer+"/api/accounts/deviceauth/token", "application/json", strings.NewReader(string(reqBody)), @@ -410,7 +413,8 @@ func RefreshAccessToken(cred *AuthCredential, cfg OAuthProviderConfig) (*AuthCre tokenURL = cfg.TokenURL } - resp, err := http.PostForm(tokenURL, data) + client := &http.Client{Timeout: 15 * time.Second} + resp, err := client.PostForm(tokenURL, data) if err != nil { return nil, fmt.Errorf("refreshing token: %w", err) } @@ -506,7 +510,8 @@ func ExchangeCodeForTokens(cfg OAuthProviderConfig, code, codeVerifier, redirect provider = "google-antigravity" } - resp, err := http.PostForm(tokenURL, data) + client := &http.Client{Timeout: 15 * time.Second} + resp, err := client.PostForm(tokenURL, data) if err != nil { return nil, fmt.Errorf("exchanging code for tokens: %w", err) }