diff --git a/internal/logs/sanitizer.go b/internal/logs/sanitizer.go index 24dacba8d..863411395 100644 --- a/internal/logs/sanitizer.go +++ b/internal/logs/sanitizer.go @@ -66,10 +66,10 @@ func (s *SecretSanitizer) registerDefaultPatterns() { }, }) - // Anthropic API keys (sk-ant-...) + // Anthropic API keys (sk-ant-...); the body is base64url, so it carries '_'. s.patterns = append(s.patterns, &secretPattern{ name: "anthropic_key", - regex: regexp.MustCompile(`\b(sk-ant-[A-Za-z0-9\-]{30,})\b`), + regex: regexp.MustCompile(`\b(sk-ant-[A-Za-z0-9_\-]{30,})\b`), maskFunc: func(key string) string { if len(key) <= 10 { return "****" diff --git a/internal/logs/sanitizer_anthropic_key_test.go b/internal/logs/sanitizer_anthropic_key_test.go new file mode 100644 index 000000000..c5cec7c09 --- /dev/null +++ b/internal/logs/sanitizer_anthropic_key_test.go @@ -0,0 +1,23 @@ +package logs + +import ( + "strings" + "testing" +) + +func TestSanitizer_AnthropicKeyWithUnderscore(t *testing.T) { + s := newTestSanitizer() + for _, key := range []string{ + "sk-ant-api03-abcdefghij_klmnopqrstuvwxyz0123456789ABCDEFGHIJ-abcdefghijklmnopqrstuvwx_yzAA", + "sk-ant-api03-abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJ_abcdefghijklmnopqrstuvwx-yzAA", + "sk-ant-admin01-Ab_Cd-EfGhIjKlMnOpQrStUvWxYz0123456789AA", + } { + out := s.sanitizeString("using key " + key + " for upstream") + if strings.Contains(out, key[16:]) { + t.Errorf("anthropic key leaked: %q", out) + } + if !strings.Contains(out, key[:10]+"***") { + t.Errorf("anthropic key not masked by anthropic_key: %q", out) + } + } +}