Security audit finding, commit abf4e87.
File: src/server.ts:213-227 (injectIntoFirstChunk)
Attack / Failure scenario
injectIntoFirstChunk decodes only the first chunk with decoder.decode(chunk, { stream: true }), re-encodes it, then discards the decoder and passes all later chunks through raw.
If the first chunk ends mid-UTF-8-sequence, the incomplete tail is buffered inside the (now discarded) decoder and lost, while the next raw chunk carries the continuation bytes → mojibake / corrupted output.
Currently latent because the skeleton is emitted as one complete chunk, but correctness then depends on the transport never re-chunking the stream.
Suggested fix
Decode the incomplete trailing bytes into a carry buffer and prepend them to the next chunk, or use a single stateful TextDecoder flushed at the boundary rather than discarding it after the first chunk.
Security audit finding, commit
abf4e87.File:
src/server.ts:213-227(injectIntoFirstChunk)Attack / Failure scenario
injectIntoFirstChunkdecodes only the first chunk withdecoder.decode(chunk, { stream: true }), re-encodes it, then discards the decoder and passes all later chunks through raw.If the first chunk ends mid-UTF-8-sequence, the incomplete tail is buffered inside the (now discarded) decoder and lost, while the next raw chunk carries the continuation bytes → mojibake / corrupted output.
Currently latent because the skeleton is emitted as one complete chunk, but correctness then depends on the transport never re-chunking the stream.
Suggested fix
Decode the incomplete trailing bytes into a carry buffer and prepend them to the next chunk, or use a single stateful
TextDecoderflushed at the boundary rather than discarding it after the first chunk.