Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions pkg/secrets/redact.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@
// and ignores surrounding whitespace. Keys that normalize to an empty
// string are ignored.
//
// If all provided keys normalize to empty strings and there are no
// existing redaction keys configured, this option returns
// ErrInvalidRedactorConfig.
// If all provided keys normalize to empty strings (e.g., all whitespace),
// this option returns ErrInvalidRedactorConfig, regardless of whether
// existing redaction keys are already configured.
func WithRedactionKeys(keys ...string) RedactorOption {
return func(cfg *redactorOptions) error {
if len(keys) == 0 {
Expand All @@ -85,16 +85,18 @@
cfg.keys = make(map[string]struct{})
}

addedCount := 0
for _, key := range keys {

Check failure on line 89 in pkg/secrets/redact.go

View workflow job for this annotation

GitHub Actions / lint

missing whitespace above this line (no shared variables above range) (wsl_v5)
value := normalizeRedactionKey(key)
if value == "" {
continue
}

cfg.keys[value] = struct{}{}
addedCount++
}

if len(cfg.keys) == 0 {
if addedCount == 0 {
return ErrInvalidRedactorConfig
}

Expand Down
55 changes: 55 additions & 0 deletions pkg/secrets/secrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,58 @@ func TestRedactorDetector(t *testing.T) {
t.Fatalf("expected detector to redact note")
}
}

func TestWithRedactionKeysValidation(t *testing.T) {
t.Run("all whitespace keys should fail even with default keys", func(t *testing.T) {
// This test verifies the fix for the validation inconsistency.
// Even when cfg.keys has default keys, passing all-whitespace keys should fail.
_, err := NewRedactor(WithRedactionKeys(" ", "\t", "\n"))
if err != ErrInvalidRedactorConfig {
t.Fatalf("expected ErrInvalidRedactorConfig when all keys are whitespace, got %v", err)
}
})

t.Run("empty keys slice should fail", func(t *testing.T) {
_, err := NewRedactor(WithRedactionKeys())
if err != ErrInvalidRedactorConfig {
t.Fatalf("expected ErrInvalidRedactorConfig for empty keys, got %v", err)
}
})

t.Run("valid keys should succeed", func(t *testing.T) {
redactor, err := NewRedactor(WithRedactionKeys("custom_key"))
if err != nil {
t.Fatalf("expected redactor with valid key, got %v", err)
}

fields := map[string]any{
"custom_key": "secret",
"other": "public",
}

redacted := redactor.RedactFields(fields)
if redacted["custom_key"] == "secret" {
t.Fatalf("expected custom_key to be redacted")
}
if redacted["other"] != "public" {
t.Fatalf("expected other field to remain unchanged")
}
})

t.Run("mix of valid and invalid keys should succeed", func(t *testing.T) {
// At least one valid key means the option should succeed
redactor, err := NewRedactor(WithRedactionKeys(" ", "valid_key", "\t"))
if err != nil {
t.Fatalf("expected redactor when at least one key is valid, got %v", err)
}

fields := map[string]any{
"valid_key": "secret",
}

redacted := redactor.RedactFields(fields)
if redacted["valid_key"] == "secret" {
t.Fatalf("expected valid_key to be redacted")
}
})
}
Loading