Skip to content

Commit 758e915

Browse files
d-csclaude
andcommitted
test(webapp): lock in byte-integrity for single-call res.end paths
patchedWrite applies isStreamingContentType / MAX_BUFFER_BYTES bypass checks before buffering; patchedEnd does not, since a single-call res.end(chunk) is not a streaming pileup scenario. These tests pin that contract by verifying byte integrity for the two shapes a single-call end can take: - octet-stream body via res.end(binary) — all 512 bytes spanning the 0-255 range round-trip byte-perfect - 80KB JSON body via res.end(buffer) — payload intact, no truncation or mangling from being buffered past the cap Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 732f8d4 commit 758e915

1 file changed

Lines changed: 52 additions & 0 deletions

File tree

apps/webapp/test/apiErrorBoundary.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,58 @@ describe("apiErrorBoundary", () => {
238238
expect(response.body).toEqual({ part1: "hello", part2: "world" });
239239
});
240240

241+
// CodeRabbit raised a concern that patchedEnd doesn't re-apply the
242+
// isStreamingContentType / MAX_BUFFER_BYTES bypass checks for single-call
243+
// `res.end(chunk)` paths. The bypasses exist for streaming pileup; a
244+
// single-call end isn't streaming, so the body is fully assembled either
245+
// way. These two tests lock in that no harm occurs: bytes flow through
246+
// unchanged for the scenarios CodeRabbit named (octet-stream content-type
247+
// and >64KB body via single-call res.end).
248+
test("preserves bytes for octet-stream body delivered via single-call res.end(chunk)", async () => {
249+
const app = buildApp();
250+
// Construct binary bytes that span the full 0-255 range to catch any
251+
// accidental encoding interpretation.
252+
const binary = Buffer.from(Array.from({ length: 512 }, (_, i) => i % 256));
253+
254+
app.get("/api/v1/octet-end", (_req, res) => {
255+
res.statusCode = 200;
256+
res.setHeader("Content-Type", "application/octet-stream");
257+
res.end(binary);
258+
});
259+
260+
const response = await request(app)
261+
.get("/api/v1/octet-end")
262+
.buffer(true)
263+
.parse((res, cb) => {
264+
const chunks: Buffer[] = [];
265+
res.on("data", (c: Buffer) => chunks.push(c));
266+
res.on("end", () => cb(null, Buffer.concat(chunks)));
267+
});
268+
269+
expect(response.status).toBe(200);
270+
expect(Buffer.compare(response.body as Buffer, binary)).toBe(0);
271+
});
272+
273+
test("preserves bytes for >64KB body delivered via single-call res.end(chunk)", async () => {
274+
const app = buildApp();
275+
const payload = JSON.stringify({
276+
filler: "x".repeat(80 * 1024),
277+
marker: "END_OF_LARGE_BODY",
278+
});
279+
280+
app.get("/api/v1/large-end", (_req, res) => {
281+
res.statusCode = 200;
282+
res.setHeader("Content-Type", "application/json");
283+
res.end(Buffer.from(payload, "utf8"));
284+
});
285+
286+
const response = await request(app).get("/api/v1/large-end");
287+
288+
expect(response.status).toBe(200);
289+
expect(response.body.filler).toHaveLength(80 * 1024);
290+
expect(response.body.marker).toBe("END_OF_LARGE_BODY");
291+
});
292+
241293
// The actual production leak path: Remix's returnLastResortErrorResponse
242294
// returns Content-Type: text/plain in non-production mode with the raw
243295
// error message appended. Our middleware must detect the leak in text/plain

0 commit comments

Comments
 (0)