fix: recognize case-insensitive signed URL schemes across log paths
This commit is contained in:
@@ -158,7 +158,7 @@ func RedactJSON(body []byte) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
urlInText = regexp.MustCompile(`(?:https?|wss?)://[^\s<>"']+`)
|
urlInText = regexp.MustCompile(`(?i)(?:https?|wss?)://[^\s<>"']+`)
|
||||||
authHeaderInText = regexp.MustCompile(`(?im)\b(?:proxy-authorization|authorization|set-cookie|cookie)["']?\s*[=:]\s*[^\r\n]+`)
|
authHeaderInText = regexp.MustCompile(`(?im)\b(?:proxy-authorization|authorization|set-cookie|cookie)["']?\s*[=:]\s*[^\r\n]+`)
|
||||||
privatePEMInText = regexp.MustCompile(`(?s)-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----.*?(?:-----END [A-Z0-9 ]*PRIVATE KEY-----|$)`)
|
privatePEMInText = regexp.MustCompile(`(?s)-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----.*?(?:-----END [A-Z0-9 ]*PRIVATE KEY-----|$)`)
|
||||||
sensitiveTextLine = regexp.MustCompile(`(?im)\b(?:prompt|system[_-]?prompt|messages|transcript|text|content|audio|closing[_-]?remark)\s*[=:]\s*[^\r\n]+`)
|
sensitiveTextLine = regexp.MustCompile(`(?im)\b(?:prompt|system[_-]?prompt|messages|transcript|text|content|audio|closing[_-]?remark)\s*[=:]\s*[^\r\n]+`)
|
||||||
|
|||||||
@@ -61,6 +61,60 @@ func TestContentFieldClassificationAndEveryLoggingPathAgree(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestURLSchemeCaseCannotExposeSignedPartsOnAnyLoggingPath(t *testing.T) {
|
||||||
|
for _, scheme := range []string{"http", "HTTP", "HtTp", "https", "HTTPS", "hTtPs", "ws", "WS", "wS", "wss", "WSS", "wSs"} {
|
||||||
|
signed := scheme + "://storage.example/audio.wav?sv=2025-01-05&se=2026-10-10&sig=private-signature-value"
|
||||||
|
for _, debug := range []bool{false, true} {
|
||||||
|
out := installTestLogger(t, debug)
|
||||||
|
for _, media := range []string{"text/plain", "application/json"} {
|
||||||
|
body := "upload failed: " + signed
|
||||||
|
if media == "application/json" {
|
||||||
|
body = `{"resource":"` + signed + `","task_id":4,"status":"ready"}`
|
||||||
|
}
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
got, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil || string(got) != body {
|
||||||
|
t.Error("wire request changed", err)
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", media)
|
||||||
|
_, _ = io.WriteString(w, body)
|
||||||
|
}))
|
||||||
|
req, err := http.NewRequest(http.MethodPost, ts.URL, strings.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", media)
|
||||||
|
response, err := HTTPClient(ts.Client(), "test.url", "upstream").Do(req)
|
||||||
|
if err != nil {
|
||||||
|
ts.Close()
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
got, err := io.ReadAll(response.Body)
|
||||||
|
_ = response.Body.Close()
|
||||||
|
ts.Close()
|
||||||
|
if err != nil || string(got) != body {
|
||||||
|
t.Fatal("wire response changed", err)
|
||||||
|
}
|
||||||
|
slog.Error("upload failed", "error", errors.New(body), "detail", body)
|
||||||
|
slog.Error(body)
|
||||||
|
}
|
||||||
|
text := out.String()
|
||||||
|
if strings.Contains(text, "private-signature-value") || strings.Contains(text, "sv=2025") || strings.Contains(text, "se=2026") {
|
||||||
|
t.Fatalf("scheme %s debug %v leak: %s", scheme, debug, text)
|
||||||
|
}
|
||||||
|
for _, keep := range []string{"upload failed", "audio.wav", "task_id", "ready"} {
|
||||||
|
if !strings.Contains(text, keep) {
|
||||||
|
t.Fatal("safe diagnostic lost", text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plain := scheme + "://storage.example/public.wav"
|
||||||
|
if got := cleanString(plain); got != plain {
|
||||||
|
t.Fatal("unsigned URL changed", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPercentEncodedSingleAndMixedFormsKeepWireBytesAndHideSecrets(t *testing.T) {
|
func TestPercentEncodedSingleAndMixedFormsKeepWireBytesAndHideSecrets(t *testing.T) {
|
||||||
for _, body := range []string{
|
for _, body := range []string{
|
||||||
"%74oken=private-access-token",
|
"%74oken=private-access-token",
|
||||||
|
|||||||
Reference in New Issue
Block a user