fix(log): redact marked secrets in every field type

redactSecrets only looked at strings, maps and errors, so a marked secret
inside a slice, struct or []byte field was logged as is, and a typed-nil
error field made it panic. It now renders each field with fmt.Sprint, as
the text formatter does (which also survives typed-nil errors), and writes
[]byte raw.

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan 2026-09-29 10:37:53 -04:00
commit 58090b42ec
2 changed files with 25 additions and 10 deletions

View file

@ -83,18 +83,12 @@ func redactSecrets(e *logrus.Entry) {
if v == nil {
continue
}
// fmt.Sprint renders like the text formatter and survives typed-nil errors; []byte is written raw.
var s string
if err, ok := v.(error); ok {
s = err.Error()
if b, ok := v.([]byte); ok {
s = string(b)
} else {
switch reflect.TypeOf(v).Kind() {
case reflect.String:
s = reflect.ValueOf(v).String()
case reflect.Map:
s = fmt.Sprintf("%+v", v)
default:
continue
}
s = fmt.Sprint(v)
}
if hidden := hide(s); hidden != s {
e.Data[k] = hidden

View file

@ -2,6 +2,7 @@ package log
import (
"errors"
"net/url"
"testing"
"github.com/sirupsen/logrus"
@ -196,6 +197,26 @@ func TestFireRedactsContextSecrets(t *testing.T) {
assert.Equal(t, namedString("untouched"), e.Data["clean"])
}
func TestFireRedactsContextSecretsInAnyValueType(t *testing.T) {
ctx := WithSecrets(t.Context(), "s3cr3t-value")
var nilErr *url.Error
e := &logrus.Entry{
Context: ctx,
Data: logrus.Fields{
"slice": []any{"s3cr3t-value", 1},
"struct": struct{ A string }{"s3cr3t-value"},
"bytes": []byte("has s3cr3t-value"),
"nilErr": nilErr,
},
}
assert.NotPanics(t, func() { _ = (&Hook{}).Fire(e) })
assert.Equal(t, "[[REDACTED] 1]", e.Data["slice"])
assert.Equal(t, "{[REDACTED]}", e.Data["struct"])
assert.Equal(t, "has [REDACTED]", e.Data["bytes"])
assert.Equal(t, nilErr, e.Data["nilErr"])
}
func TestFireWithoutContextSecretsLeavesEntryUnchanged(t *testing.T) {
args := map[string]any{"p0": "value"}
e := &logrus.Entry{Context: t.Context(), Message: "value", Data: logrus.Fields{"str": "value", "args": args}}