fix(sanitizer): strip zero-width chars from Anthropic-native streaming text_delta (#8271) (#8287)

sanitizeStreamingChunk() only stripped zero-width characters (U+200B,
U+200C, U+200D, U+FEFF) from OpenAI-format choices[].delta.content.
Anthropic-native content_block_delta events with text_delta or
thinking_delta payloads bypassed that path entirely, leaking U+200D
to clients on the Messages API streaming route.

Add a content_block_delta branch that strips zero-width characters
from delta.text and delta.thinking before returning the event,
matching the existing OpenAI path behavior from #5857.

Co-authored-by: Austin Liu <austinliu@Austins-MacBook-Air-3.local>
This commit is contained in:
Austin Liu
2026-07-23 23:36:51 +09:30
committed by GitHub
parent 99ad15a37f
commit acd3d46ab4

View File

@@ -1011,6 +1011,23 @@ export function sanitizeStreamingChunk(parsed: unknown): unknown {
return sanitizeResponsesStreamingEvent(parsedRecord);
}
// #8271: Anthropic-native streaming events (content_block_delta with
// text_delta / thinking_delta) bypass the OpenAI choices[].delta.content
// path below. Strip zero-width characters from their text payloads so
// U+200D and friends don't leak to the client on the Messages API.
if (eventType === "content_block_delta") {
const deltaRecord = toRecord(parsedRecord.delta);
if (deltaRecord) {
if (typeof deltaRecord.text === "string") {
deltaRecord.text = stripZeroWidthText(deltaRecord.text);
}
if (typeof deltaRecord.thinking === "string") {
deltaRecord.thinking = stripZeroWidthText(deltaRecord.thinking);
}
}
return parsedRecord;
}
// Build sanitized chunk
const sanitized: JsonRecord = {};