fix: retain conversation ownership across blank paragraphs
This commit is contained in:
@@ -130,11 +130,8 @@ func redactConversationLines(body string) string {
|
||||
lines := strings.SplitAfter(body, "\n")
|
||||
hiding := false
|
||||
for i, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if hiding && trimmed == "" {
|
||||
hiding = false
|
||||
continue
|
||||
}
|
||||
// Whitespace separates paragraphs inside a conversation, not records.
|
||||
// Ownership ends only at the explicit non-conversation field below.
|
||||
field := textFieldLine.FindStringSubmatch(line)
|
||||
if hiding {
|
||||
// Continuation lines and conversation speaker labels are not business
|
||||
|
||||
@@ -29,6 +29,31 @@ func TestAssociatedSensitiveControlsHideContentWithoutSwallowingBusiness(t *test
|
||||
}
|
||||
}
|
||||
|
||||
func TestConversationOwnershipPersistsAcrossBlankLines(t *testing.T) {
|
||||
for _, gap := range []string{"\n", "\n\n", "\n \n\t\n", "\r\n\r\n"} {
|
||||
for _, label := range []string{"messages", "prompt", "transcript", "content"} {
|
||||
value := "upstream failed\n" + label + ":" + gap + "user: private-user-turn" + gap + "assistant: private-assistant-turn" + gap + "status=retry_pending\nattempts=2"
|
||||
for _, debug := range []bool{false, true} {
|
||||
out := installTestLogger(t, debug)
|
||||
slog.Error("operation failed", "error", errors.New(value), "detail", value)
|
||||
slog.Info(value, "stage", "failure_observed")
|
||||
TextBody(t.Context(), "HTTP text observed", []byte(value), "transport", "http")
|
||||
text := out.String()
|
||||
for _, secret := range []string{"private-user-turn", "private-assistant-turn"} {
|
||||
if strings.Contains(text, secret) {
|
||||
t.Fatalf("label %s gap %q debug %v leak: %s", label, gap, debug, text)
|
||||
}
|
||||
}
|
||||
for _, keep := range []string{"upstream failed", "retry_pending", "attempts=2"} {
|
||||
if !strings.Contains(text, keep) {
|
||||
t.Fatal("business diagnostics lost", text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFreeTextConversationIsHiddenInBothModesAndAllScalarPaths(t *testing.T) {
|
||||
value := "upstream failed\nmessages:\nuser: private-user-turn\nassistant: private-assistant-turn\n\nstatus=retry_pending\nattempts=2"
|
||||
for _, debug := range []bool{false, true} {
|
||||
@@ -103,7 +128,7 @@ func TestReadableMarkupFormAndMultilineConversationAreSanitized(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReadablePlainHTTPBodiesAreObservedSafelyWithoutChangingBytes(t *testing.T) {
|
||||
body := "status=ready\ntask_id=4\nremaining=27\nAuthorization: Basic dXNlcjpwYXNzd29yZA==\napi_key=private-key\n-----BEGIN PRIVATE KEY-----\nprivate-pem-material\n-----END PRIVATE KEY-----\nretry_after=60\n" + strings.Repeat("business-data ", 12000)
|
||||
body := "status=ready\ntask_id=4\nremaining=27\nmessages:\n\nuser: private-http-user-turn\n\nassistant: private-http-assistant-turn\n\nstatus=ready\nAuthorization: Basic dXNlcjpwYXNzd29yZA==\napi_key=private-key\n-----BEGIN PRIVATE KEY-----\nprivate-pem-material\n-----END PRIVATE KEY-----\nretry_after=60\n" + strings.Repeat("business-data ", 12000)
|
||||
for _, debug := range []bool{false, true} {
|
||||
out := installTestLogger(t, debug)
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -127,7 +152,7 @@ func TestReadablePlainHTTPBodiesAreObservedSafelyWithoutChangingBytes(t *testing
|
||||
t.Fatal("response changed", err)
|
||||
}
|
||||
text := out.String()
|
||||
for _, secret := range []string{"dXNlcjpwYXNzd29yZA==", "private-key", "private-pem-material"} {
|
||||
for _, secret := range []string{"dXNlcjpwYXNzd29yZA==", "private-key", "private-pem-material", "private-http-user-turn", "private-http-assistant-turn"} {
|
||||
if strings.Contains(text, secret) {
|
||||
t.Fatalf("leak %s", secret)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user