fix(proxy): keep Burst/Endpoints in ratelimit unmarshal; redact large truncated log bodies

- ratelimit: custom UnmarshalJSON temp struct only carried interval/req,
  silently dropping the configured 'burst' and 'endpoints' fields. Burst is
  consumed at checkRateLimit (burst allowance) but could never be set via
  config file. Carry all fields in the temp struct.
- sanitization: a large non-parsable body was truncated before redaction,
  potentially leaking a secret in the first MaxLogBodySize bytes, and the
  truncation could split a multi-byte UTF-8 rune. Redact the retained
  prefix and truncate on a rune boundary (sanitizeTruncatedBody).
- tests: TestRateLimitConfigUnmarshalKeepsBurstAndEndpoints,
  TestSanitizeTruncatedBodyRedactsAndKeepsUTF8, TestTruncateUTF8RuneBoundary.
This commit is contained in:
2026-08-13 05:55:36 +01:00
parent dd2aa922c5
commit fc28c65681
4 changed files with 102 additions and 7 deletions
+11 -4
View File
@@ -23,10 +23,15 @@ type RateLimitConfig struct {
// UnmarshalJSON implements custom JSON unmarshaling for RateLimitConfig
func (r *RateLimitConfig) UnmarshalJSON(data []byte) error {
// Use a temporary struct to unmarshal the JSON data
// Use a temporary struct to unmarshal the JSON data.
// It must carry every configurable field: Burst (used by the burst
// allowance at the top of checkRateLimit) and Endpoints would otherwise be
// silently dropped from the loaded config and left at their zero values.
type RateLimitConfigTemp struct {
Interval any `json:"interval"`
Req int `json:"req"`
Interval any `json:"interval"`
Burst int `json:"burst,omitempty"`
Endpoints []string `json:"endpoints,omitempty"`
Req int `json:"req"`
}
var temp RateLimitConfigTemp
@@ -34,8 +39,10 @@ func (r *RateLimitConfig) UnmarshalJSON(data []byte) error {
return err
}
// Set the Req field directly
// Set the Req, Burst and Endpoints fields directly
r.Req = temp.Req
r.Burst = temp.Burst
r.Endpoints = temp.Endpoints
// Handle the Interval field based on its type
switch v := temp.Interval.(type) {