diff --git a/sdk/cliproxy/session/identity.go b/sdk/cliproxy/session/identity.go index 84a3a653c..696e0372a 100644 --- a/sdk/cliproxy/session/identity.go +++ b/sdk/cliproxy/session/identity.go @@ -42,15 +42,15 @@ type canonicalPart struct { // NormalizeExplicitID validates an explicit client-provided session identifier. // It preserves opaque printable values while rejecting oversized or control-bearing IDs. func NormalizeExplicitID(raw string) string { - raw = strings.TrimSpace(raw) - if raw == "" || len(raw) > 256 { - return "" - } for _, r := range raw { if unicode.IsControl(r) { return "" } } + raw = strings.TrimSpace(raw) + if raw == "" || len(raw) > 256 { + return "" + } return raw } diff --git a/sdk/cliproxy/session/identity_test.go b/sdk/cliproxy/session/identity_test.go index a8cad079c..7211d3798 100644 --- a/sdk/cliproxy/session/identity_test.go +++ b/sdk/cliproxy/session/identity_test.go @@ -244,6 +244,14 @@ func TestEnrichDerivesAfterInvalidSessionIdentity(t *testing.T) { name: "oversized prompt cache key", payload: []byte(`{"prompt_cache_key":"` + strings.Repeat("x", 257) + `",` + baseMessages + `}`), }, + { + name: "trailing control character prompt cache key", + payload: []byte(`{"prompt_cache_key":"tenant\n",` + baseMessages + `}`), + }, + { + name: "leading control character prompt cache key", + payload: []byte(`{"prompt_cache_key":"\ttenant",` + baseMessages + `}`), + }, { name: "control character session header", payload: []byte(`{` + baseMessages + `}`),