Satisfy gosec on the proxy count and the request log
CI / chart (pull_request) Successful in 3s
CI / security (pull_request) Successful in 25s
CI / test (pull_request) Successful in 5m42s

G115: the trusted-proxy count is stored as an int64 instead of narrowing
it to int32. G706: the request logger and serverError quote the request
method and route; the logger's remaining taint comes from the wrapped
response writer, so it carries a justified nosec like the other quoted log
lines.

Claude-Session: https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN
This commit is contained in:
Niklas Ye
2026-10-09 15:27:45 +02:00
parent eb63e5e138
commit 01922291f6
4 changed files with 4 additions and 4 deletions
+1 -1
View File
@@ -132,7 +132,7 @@ func purgeRateLimits(ctx context.Context, db *sql.DB) {
// trustedProxies is how many X-Forwarded-For hops clientAddr trusts. Set once // trustedProxies is how many X-Forwarded-For hops clientAddr trusts. Set once
// by NewRouter from config. // by NewRouter from config.
var trustedProxies atomic.Int32 var trustedProxies atomic.Int64
// clientAddr is the address a login is counted against. Behind the gateway // clientAddr is the address a login is counted against. Behind the gateway
// RemoteAddr is the gateway itself, so the client address is read from // RemoteAddr is the gateway itself, so the client address is read from
+1 -1
View File
@@ -77,7 +77,7 @@ func serverError(w http.ResponseWriter, r *http.Request, err error) {
if rc := chi.RouteContext(r.Context()); rc != nil && rc.RoutePattern() != "" { if rc := chi.RouteContext(r.Context()); rc != nil && rc.RoutePattern() != "" {
route = rc.RoutePattern() route = rc.RoutePattern()
} }
log.Printf("%s %s: %v", r.Method, route, err) log.Printf("%s %s: %v", strconv.Quote(r.Method), strconv.Quote(route), err)
respond(w, http.StatusInternalServerError, errResp("internal error")) respond(w, http.StatusInternalServerError, errResp("internal error"))
} }
+1 -1
View File
@@ -447,6 +447,6 @@ func requestLogger(next http.Handler) http.Handler {
if status == 0 { if status == 0 {
status = http.StatusOK status = http.StatusOK
} }
log.Printf("%s %s %d %dB %s", r.Method, route, status, ww.BytesWritten(), time.Since(start).Round(time.Millisecond)) log.Printf("%q %q %d %dB %s", r.Method, route, status, ww.BytesWritten(), time.Since(start).Round(time.Millisecond)) // #nosec G706 -- method and route are %q-quoted, the route is a registered pattern, the rest are numbers
}) })
} }
+1 -1
View File
@@ -23,7 +23,7 @@ func NewRouter(db *sql.DB, notify NotifyConfig, cfg config.Config, version strin
// One limiter each, both process-wide for the life of the router: login // One limiter each, both process-wide for the life of the router: login
// counts failed passwords, sign-up counts account creation, and mixing the // counts failed passwords, sign-up counts account creation, and mixing the
// two would let a burst of sign-ups lock somebody out of logging in. // two would let a burst of sign-ups lock somebody out of logging in.
trustedProxies.Store(int32(cfg.TrustedProxies)) trustedProxies.Store(int64(cfg.TrustedProxies))
loginLimit := newLoginLimiter(db) loginLimit := newLoginLimiter(db)
signupLimiter := newLoginLimiter(db) signupLimiter := newLoginLimiter(db)
oidcLimit := newLoginLimiter(db) oidcLimit := newLoginLimiter(db)