Lint: fix real int-truncation bug; document intentional gosec findings

- TransportPool configKey: write conn-count ints verbatim (strconv) instead of
  byte() truncation — a config value >=256 previously truncated and made two
  distinct configs collide on one key, silently sharing a transport with the
  wrong settings (real fix, gosec G115).
- Document design-intentional gosec findings with //nolint:gosec + rationale:
  G117 (clients_secret intentionally marshaled into stored creds JSON),
  G704 (tokenURL is the trusted discovery endpoint), G124 (delete/test cookie,
  Secure set conditionally), G118 (long-lived background refresh) and pool
  utils short-ID rune, testutil mock server redirects.

Result: full-tree golangci-lint now reports 0 issues (was ~12). Build, vet,
and the full test suite remain green.
This commit is contained in:
2026-08-12 23:10:00 +01:00
parent 2ff14556d0
commit 7d2531e1e4
10 changed files with 21 additions and 14 deletions
+1 -1
View File
@@ -78,7 +78,7 @@ func (s *FileStore) Save(ctx context.Context, providerURL string, creds *ClientR
return fmt.Errorf("failed to create credentials directory: %w", err)
}
data, err := json.MarshalIndent(creds, "", " ")
data, err := json.MarshalIndent(creds, "", " ") //nolint:gosec // ClientSecret must be persisted; creds are the feature's output
if err != nil {
return fmt.Errorf("failed to marshal credentials: %w", err)
}
+1 -1
View File
@@ -86,7 +86,7 @@ func (s *RedisStore) Save(ctx context.Context, providerURL string, creds *Client
}
// Serialize credentials to JSON for storage
data, err := json.Marshal(creds)
data, err := json.Marshal(creds) //nolint:gosec // secret intentionally serialized for Redis storage
if err != nil {
return fmt.Errorf("failed to marshal credentials: %w", err)
}
+10 -3
View File
@@ -5,6 +5,7 @@ import (
"crypto/tls"
"net"
"net/http"
"strconv"
"sync"
"sync/atomic"
"time"
@@ -246,9 +247,15 @@ func (p *TransportPool) configKey(config TransportConfig) string {
sb := Get().GetStringBuilder()
defer Get().PutStringBuilder(sb)
sb.WriteByte(byte(config.MaxConnsPerHost))
sb.WriteByte(byte(config.MaxIdleConnsPerHost))
sb.WriteByte(byte(config.MaxIdleConns))
// Write the int fields verbatim, not byte()s: a config value >=256 would
// otherwise truncate and make two distinct configs collide on one key,
// silently sharing a single transport with the wrong settings.
sb.WriteString(strconv.Itoa(config.MaxConnsPerHost))
sb.WriteByte('|')
sb.WriteString(strconv.Itoa(config.MaxIdleConnsPerHost))
sb.WriteByte('|')
sb.WriteString(strconv.Itoa(config.MaxIdleConns))
sb.WriteByte('|')
if config.ForceHTTP2 {
sb.WriteByte(1)
} else {
+1 -1
View File
@@ -14,7 +14,7 @@ func BuildSessionName(baseName string, index int) string {
sb.WriteRune('_')
// Efficient int to string conversion
if index < 10 {
sb.WriteRune('0' + rune(index))
sb.WriteRune('0' + rune(index)) //nolint:gosec // index is bounded by the short alphabet size
} else {
sb.WriteString(intToString(index))
}
+2 -2
View File
@@ -279,7 +279,7 @@ func (s *OIDCServer) handleAuthorize(w http.ResponseWriter, r *http.Request) {
}
redirectURL := fmt.Sprintf("%s?code=test-auth-code&state=%s", redirectURI, state)
http.Redirect(w, r, redirectURL, http.StatusFound)
http.Redirect(w, r, redirectURL, http.StatusFound) //nolint:gosec // mock IdP redirects to its configured (trusted) endpoint
}
func (s *OIDCServer) handleUserinfo(w http.ResponseWriter, r *http.Request) {
@@ -342,7 +342,7 @@ func (s *OIDCServer) handleLogout(w http.ResponseWriter, r *http.Request) {
http.Error(w, "invalid post_logout_redirect_uri", http.StatusBadRequest)
return
}
http.Redirect(w, r, postLogoutRedirect, http.StatusFound)
http.Redirect(w, r, postLogoutRedirect, http.StatusFound) //nolint:gosec // mock IdP post-logout redirect
return
}
+1 -1
View File
@@ -72,7 +72,7 @@ func (s *OIDCSuite) NewRequest(method, path string) *http.Request {
// NewRequestWithCookie creates a request with a session cookie
func (s *OIDCSuite) NewRequestWithCookie(method, path, cookieName, cookieValue string) *http.Request {
req := s.NewRequest(method, path)
req.AddCookie(&http.Cookie{
req.AddCookie(&http.Cookie{ //nolint:gosec // test cookie on an httptest request
Name: cookieName,
Value: cookieValue,
})