package tools import "testing" func TestScrubCredentials_OpenAI(t *testing.T) { input := "Found key: sk-abcdefghijklmnopqrstuvwxyz1234567890 in env" got := ScrubCredentials(input) if got != "Found key: [REDACTED] in env" { t.Errorf("OpenAI key not scrubbed: %s", got) } } func TestScrubCredentials_Anthropic(t *testing.T) { input := "key=sk-ant-abc123-def456-ghi789-jkl012" got := ScrubCredentials(input) if got != "key=[REDACTED]" { t.Errorf("Anthropic key not scrubbed: %s", got) } } func TestScrubCredentials_GitHub(t *testing.T) { tests := []struct { name string input string }{ {"ghp", "token ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij done"}, {"gho", "token gho_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij done"}, {"ghu", "token ghu_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij done"}, {"ghs", "token ghs_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij done"}, {"ghr", "token ghr_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij done"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := ScrubCredentials(tt.input) want := "token [REDACTED] done" if got != want { t.Errorf("GitHub %s not scrubbed: got %q, want %q", tt.name, got, want) } }) } } func TestScrubCredentials_AWS(t *testing.T) { input := "aws_key: AKIAIOSFODNN7EXAMPLE" got := ScrubCredentials(input) if got == input { t.Errorf("AWS key not scrubbed: %s", got) } } func TestScrubCredentials_GenericKeyValue(t *testing.T) { tests := []struct { name string input string }{ {"api_key", "api_key=supersecretvalue123"}, {"token", "token: mysecrettoken12345"}, {"password", "password=MyStr0ngP@ssword!"}, {"bearer", "bearer: eyJhbGciOiJIUzI1NiJ9.abc"}, {"authorization", "authorization=eyJhbGciOiJIUzI1NiJ9abcdef"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := ScrubCredentials(tt.input) if got == tt.input { t.Errorf("generic pattern %q not scrubbed: %s", tt.name, got) } }) } } func TestScrubCredentials_NoFalsePositive(t *testing.T) { inputs := []string{ "hello world", "sk-short", // too short for OpenAI pattern "ghp_tooshort", // too short for GitHub pattern "normal text with no secrets", "AKIA1234", // too short for AWS (needs 16 chars after AKIA) } for _, input := range inputs { got := ScrubCredentials(input) if got != input { t.Errorf("false positive on %q: got %q", input, got) } } } func TestScrubCredentials_MultiplePatterns(t *testing.T) { input := "openai=sk-abcdefghijklmnopqrstuvwxyz, github=ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij" got := ScrubCredentials(input) if got == input { t.Errorf("multiple patterns not scrubbed: %s", got) } } func TestScrubCredentials_EmptyString(t *testing.T) { got := ScrubCredentials("") if got != "" { t.Errorf("empty string changed: %q", got) } } func TestScrubCredentials_DynamicServerIPs(t *testing.T) { ResetDynamicScrubValues() defer ResetDynamicScrubValues() AddDynamicScrubValues("18.141.232.136", "34.160.111.145") tests := []struct { name string input string want string }{ {"public IP", "Your IP: 18.141.232.136", "Your IP: [SERVER_IP]"}, {"forwarded chain", "X-Forwarded-For: 18.141.232.136, 34.160.111.145", "X-Forwarded-For: [SERVER_IP], [SERVER_IP]"}, {"unrelated IP", "Hello 1.2.3.4", "Hello 1.2.3.4"}, {"IP in URL", "http://18.141.232.136:8080/api", "http://[SERVER_IP]:8080/api"}, {"multiple occurrences", "src=18.141.232.136 dst=18.141.232.136", "src=[SERVER_IP] dst=[SERVER_IP]"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := ScrubCredentials(tt.input) if got != tt.want { t.Errorf("got %q, want %q", got, tt.want) } }) } } func TestAddDynamicScrubValues_Dedup(t *testing.T) { ResetDynamicScrubValues() defer ResetDynamicScrubValues() AddDynamicScrubValues("10.0.0.1", "10.0.0.1", "10.0.0.2") if count := DynamicScrubCount(); count != 2 { t.Errorf("expected 2 unique values, got %d", count) } } func TestAddDynamicScrubValues_IgnoresEmpty(t *testing.T) { ResetDynamicScrubValues() defer ResetDynamicScrubValues() AddDynamicScrubValues("", "", "10.0.0.1") if count := DynamicScrubCount(); count != 1 { t.Errorf("expected 1 value, got %d", count) } } func TestDetectLocalIPs_NoLoopback(t *testing.T) { ips := detectLocalIPs() for _, ipStr := range ips { if ipStr == "127.0.0.1" || ipStr == "::1" { t.Errorf("loopback IP should be excluded: %s", ipStr) } } }