mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 17:45:53 +01:00
The in-sandbox gateway charged request-body admission on the raw source bytes, but it retained and forwarded more bytes than it charged. Two defects allowed a body to exceed the charged bytes. First, readBody returned a UTF-8 string. The duplex gateway re-encoded that string to a Buffer. Each invalid byte became the 3-byte U+FFFD replacement, so a cap-sized malformed body expanded to about 3x the charged bytes after admission. Preserve the raw request bytes end to end: readBody now returns the raw Buffer and the duplex gateway uses it directly. The base64 frames and the envelope byte count now equal the wire bytes, so a malformed body cannot expand. Second, the duplex path held the raw body plus the full base64 frame array plus the full encoded-line array at once, about 3.7x the raw body. Stream the body as body_chunk frames one at a time, so the gateway holds the raw body plus at most one frame. The retained peak per read is now about the charged bytes plus 1 MB, so the inflight bound bounds the true retained bytes. The file gateway writes the body as a JSON string that the host reader consumes. It rejects an invalid-UTF-8 body with a clean 400 before it converts the body, so it does not amplify a malformed body and keeps the on-disk payload contract unchanged. Tests: a cap-sized malformed-UTF-8 body forwards byte-for-byte with no expanded frame; the admission bound caps concurrent reads at the retained-byte model; the file gateway answers 400 for an invalid body and forwards nothing. Co-authored-by: Paperclip <noreply@paperclip.ing>