This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
package redaction
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const replacement = "<redacted>"
|
||||
|
||||
var sensitivePattern = regexp.MustCompile(`(?i)(authorization|cookie|password|passwd|secret|token|api[_-]?key|client[_-]?secret)(\s*[:=]\s*)(?:bearer\s+)?([^,;\s]+)`)
|
||||
|
||||
func String(value string) string {
|
||||
return sensitivePattern.ReplaceAllString(value, `$1$2`+replacement)
|
||||
}
|
||||
|
||||
func Value(key string, value any) any {
|
||||
if sensitiveKey(key) {
|
||||
return replacement
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func Map(values map[string]any) map[string]any {
|
||||
clean := make(map[string]any, len(values))
|
||||
for key, value := range values {
|
||||
clean[key] = Value(key, value)
|
||||
}
|
||||
return clean
|
||||
}
|
||||
|
||||
func sensitiveKey(key string) bool {
|
||||
key = strings.ToLower(strings.ReplaceAll(strings.ReplaceAll(key, "-", "_"), " ", "_"))
|
||||
for _, part := range []string{"authorization", "cookie", "password", "passwd", "secret", "token", "api_key", "apikey", "client_secret"} {
|
||||
if strings.Contains(key, part) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package redaction
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStringRedactsSecretFixtures(t *testing.T) {
|
||||
input := "authorization=Bearer abc123 password=hunter2 token=secret-token endpoint=https://example"
|
||||
output := String(input)
|
||||
for _, secret := range []string{"abc123", "hunter2", "secret-token"} {
|
||||
if strings.Contains(output, secret) {
|
||||
t.Errorf("secret %q leaked in %q", secret, output)
|
||||
}
|
||||
}
|
||||
if !strings.Contains(output, "<redacted>") {
|
||||
t.Fatal("redaction marker missing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapRedactsSensitiveKeysOnly(t *testing.T) {
|
||||
output := Map(map[string]any{"client_secret": "secret", "display_name": "Pulse"})
|
||||
if output["client_secret"] != replacement || output["display_name"] != "Pulse" {
|
||||
t.Fatalf("unexpected map: %#v", output)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user