Files
claude-mnemonic/internal/privacy/secrets_test.go
T

214 lines
4.7 KiB
Go

package privacy
import (
"testing"
)
func TestContainsSecrets(t *testing.T) {
tests := []struct {
name string
input string
expected bool
}{
{
name: "empty string",
input: "",
expected: false,
},
{
name: "normal text",
input: "This is just some regular text about a bug fix",
expected: false,
},
{
name: "API key pattern",
input: "api_key=abc123def456ghi789jkl012mno345pqr678",
expected: true,
},
{
name: "api-key with dash",
input: `api-key: "abc123def456ghi789jkl012mno"`,
expected: true,
},
{
name: "password in config",
input: `password="super_secret_password_123"`,
expected: true,
},
{
name: "OpenAI key format",
input: "sk-abc123def456ghi789jkl012mno345pqr678",
expected: true,
},
{
name: "Anthropic key format",
input: "sk-ant-api03-abc123def456ghi789jkl012mno345",
expected: true,
},
{
name: "GitHub PAT",
input: "ghp_1234567890abcdefghijklmnopqrstuvwxyz",
expected: true,
},
{
name: "GitHub PAT new format",
input: "github_pat_12ABCDEFGHIJ3456789abc_defghijklmno",
expected: true,
},
{
name: "AWS access key",
input: "AKIAIOSFODNN7EXAMPLE",
expected: true,
},
{
name: "Private key header",
input: "-----BEGIN RSA PRIVATE KEY-----",
expected: true,
},
{
name: "JWT token",
input: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
expected: true,
},
{
name: "bearer token",
input: "Bearer abc123def456ghi789jkl012mno345",
expected: true,
},
{
name: "secret_key in code",
input: `secret_key = "my_super_secret_token_here"`,
expected: true,
},
{
name: "short password is not detected",
input: `password="short"`,
expected: false, // Too short to trigger
},
{
name: "word password in sentence",
input: "The password field should be validated",
expected: false,
},
{
name: "word api in code",
input: "The API returns JSON data",
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ContainsSecrets(tt.input)
if result != tt.expected {
t.Errorf("ContainsSecrets(%q) = %v, want %v", tt.input, result, tt.expected)
}
})
}
}
func TestRedactSecrets(t *testing.T) {
tests := []struct {
name string
input string
expected string
}{
{
name: "empty string",
input: "",
expected: "",
},
{
name: "no secrets",
input: "This is safe text",
expected: "This is safe text",
},
{
name: "API key gets redacted",
input: "api_key=abc123def456ghi789jkl012mno345pqr678",
expected: "api_key=[REDACTED]",
},
{
name: "OpenAI key gets redacted",
input: "The key is sk-abc123def456ghi789jkl012mno345pqr678",
expected: "The key is sk-a...[REDACTED]",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := RedactSecrets(tt.input)
if result != tt.expected {
t.Errorf("RedactSecrets(%q) = %q, want %q", tt.input, result, tt.expected)
}
})
}
}
func TestSanitizeObservation(t *testing.T) {
tests := []struct {
name string
narrative string
facts []string
expected bool
}{
{
name: "clean observation",
narrative: "Fixed a bug in the login flow",
facts: []string{"Users can now log in", "Session management improved"},
expected: false,
},
{
name: "secret in narrative",
narrative: "Set API key api_key=abc123def456ghi789jkl012mno345",
facts: []string{"Configuration updated"},
expected: true,
},
{
name: "secret in facts",
narrative: "Updated configuration",
facts: []string{"Added api_key=abc123def456ghi789jkl012mno345"},
expected: true,
},
{
name: "empty facts",
narrative: "Clean narrative",
facts: []string{},
expected: false,
},
{
name: "nil facts",
narrative: "Clean narrative",
facts: nil,
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := SanitizeObservation(tt.narrative, tt.facts)
if result != tt.expected {
t.Errorf("SanitizeObservation() = %v, want %v", result, tt.expected)
}
})
}
}
func BenchmarkContainsSecrets(b *testing.B) {
text := "This is a normal piece of text that does not contain any secrets or sensitive information"
b.ResetTimer()
for i := 0; i < b.N; i++ {
ContainsSecrets(text)
}
}
func BenchmarkContainsSecretsWithSecret(b *testing.B) {
text := "api_key=abc123def456ghi789jkl012mno345pqr678"
b.ResetTimer()
for i := 0; i < b.N; i++ {
ContainsSecrets(text)
}
}