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) { func TestSensitiveWorkflowFieldsAndURLsNeverLeak(t *testing.T) {
out := installTestLogger(t, true) 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") 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 return -1
}, key) }, key)
switch normalized { 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 true
} }
return strings.HasSuffix(normalized, "password") || strings.HasSuffix(normalized, "secret") || strings.HasSuffix(normalized, "apikey") || strings.HasSuffix(normalized, "token") || strings.HasSuffix(normalized, "text") 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 ( var (
urlInText = regexp.MustCompile(`https?://[^\s<>"']+`) urlInText = regexp.MustCompile(`(?:https?|wss?)://[^\s<>"']+`)
bearerInText = regexp.MustCompile(`(?i)\bBearer\s+[^\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. // Error messages can contain a provider's JSON response after a text prefix.