fix: redact private keys and signed websocket endpoints

This commit is contained in:
2026-10-10 00:26:38 +08:00
parent eb173f7228
commit fd37a67ef8
2 changed files with 16 additions and 3 deletions
+13
View File
@@ -105,6 +105,19 @@ func TestUnstructuredAndEmbeddedJSONCannotLeakCredentials(t *testing.T) {
}
}
func TestPrivateKeyAndSignedWebSocketURLNeverLeakInEitherMode(t *testing.T) {
for _, debug := range []bool{false, true} {
out := installTestLogger(t, debug)
slog.Info("workflow", "private_key", "private-key-value", "client_key_pem", "private-pem-value", "endpoint", "wss://user:private-password@host/ws?Signature=private-signature")
Body(context.Background(), "HTTP data", []byte(`{"privateKey":"private-key-value","ws_endpoint":"wss://host/ws?Signature=private-signature"}`))
for _, secret := range []string{"private-key-value", "private-pem-value", "private-password", "private-signature"} {
if strings.Contains(out.String(), secret) {
t.Fatalf("leaked %s: %s", secret, out.String())
}
}
}
}
func TestSensitiveWorkflowFieldsAndURLsNeverLeak(t *testing.T) {
out := installTestLogger(t, true)
slog.Info("workflow", "Authorization", "Bearer do-not-print", "apiKey", "do-not-print", "prompt", "do-not-print", "url", "https://user:pass@host/path?signature=do-not-print")
+3 -3
View File
@@ -23,7 +23,7 @@ func sensitive(key string) bool {
return -1
}, key)
switch normalized {
case "content", "headers", "history", "sentence", "sentences", "words", "openingremark", "openingremarks", "greeting", "sessionnonce", "credential", "credentials", "key", "authorization", "proxyauthorization", "apikey", "accesskeyid", "accesskeysecret", "appkey", "appsecret", "secret", "secretkey", "password", "passwd", "token", "accesstoken", "refreshtoken", "uploadtoken", "providertoken", "sessioncredential", "clientnonce", "servernonce", "cookie", "setcookie", "prompt", "systemprompt", "instructions", "messages", "messagecontent", "transcript", "transcription", "finaltranscript", "text", "utterance", "audio", "audiodata", "recordingdata", "raw", "closingremark", "signature", "targeturl":
case "privatekey", "privatekeypem", "clientkey", "clientkeypem", "serverkey", "serverkeypem", "content", "headers", "history", "sentence", "sentences", "words", "openingremark", "openingremarks", "greeting", "sessionnonce", "credential", "credentials", "key", "authorization", "proxyauthorization", "apikey", "accesskeyid", "accesskeysecret", "appkey", "appsecret", "secret", "secretkey", "password", "passwd", "token", "accesstoken", "refreshtoken", "uploadtoken", "providertoken", "sessioncredential", "clientnonce", "servernonce", "cookie", "setcookie", "prompt", "systemprompt", "instructions", "messages", "messagecontent", "transcript", "transcription", "finaltranscript", "text", "utterance", "audio", "audiodata", "recordingdata", "raw", "closingremark", "signature", "targeturl":
return true
}
return strings.HasSuffix(normalized, "password") || strings.HasSuffix(normalized, "secret") || strings.HasSuffix(normalized, "apikey") || strings.HasSuffix(normalized, "token") || strings.HasSuffix(normalized, "text")
@@ -139,9 +139,9 @@ func RedactJSON(body []byte) (string, error) {
}
var (
urlInText = regexp.MustCompile(`https?://[^\s<>"']+`)
urlInText = regexp.MustCompile(`(?:https?|wss?)://[^\s<>"']+`)
bearerInText = regexp.MustCompile(`(?i)\bBearer\s+[^\s,;"']+`)
secretInText = regexp.MustCompile(`(?i)\b(api[_-]?key|access[_-]?key[_-]?(secret|id)|password|token|secret|signature|prompt|system[_-]?prompt|content|transcript|text)["']?\s*[=:]\s*(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|[^\s,;"']+)`)
secretInText = regexp.MustCompile(`(?i)\b(api[_-]?key|private[_-]?key(?:[_-]?pem)?|client[_-]?key(?:[_-]?pem)?|access[_-]?key[_-]?(secret|id)|password|token|secret|signature|prompt|system[_-]?prompt|content|transcript|text)["']?\s*[=:]\s*(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|[^\s,;"']+)`)
)
// Error messages can contain a provider's JSON response after a text prefix.