@@ -94,6 +94,42 @@ describe("body", () => {
|
94 | 94 | expect(await result.body.text()).toBe("200"); |
95 | 95 | }); |
96 | 96 | |
| 97 | +it("handles case-insensitive Transfer-Encoding: chunked header (CVE)", async () => { |
| 98 | +// Test that Transfer-Encoding header check is case-insensitive per RFC 7230 |
| 99 | +// This prevents HTTP Request Smuggling via TE.TE desynchronization attacks |
| 100 | + |
| 101 | +const testCases = [ |
| 102 | +{ encoding: "ChunKed", expected: '{"test":"data"}' }, |
| 103 | +{ encoding: "CHUNKED", expected: '{"test":"data"}' }, |
| 104 | +{ encoding: "Chunked", expected: '{"test":"data"}' }, |
| 105 | +]; |
| 106 | + |
| 107 | +for (const testCase of testCases) { |
| 108 | +// Simulate a raw HTTP request with mixed-case Transfer-Encoding |
| 109 | +const mockReq = { |
| 110 | +method: "POST", |
| 111 | +headers: { "transfer-encoding": testCase.encoding }, |
| 112 | +on(event: string, handler: (chunk?: Buffer) => void) { |
| 113 | +if (event === "data") { |
| 114 | +// Simulate chunked data arrival |
| 115 | +handler(Buffer.from(testCase.expected)); |
| 116 | +} else if (event === "end") { |
| 117 | +handler(); |
| 118 | +} |
| 119 | +return this; |
| 120 | +}, |
| 121 | +}; |
| 122 | + |
| 123 | +const mockEvent = { method: "POST", node: { req: mockReq } }; |
| 124 | + |
| 125 | +const result = await readRawBody(mockEvent as any); |
| 126 | + |
| 127 | +// Should properly read the body regardless of Transfer-Encoding case |
| 128 | +// If the check is case-sensitive, this will fail and return undefined |
| 129 | +expect(result).toEqual(testCase.expected); |
| 130 | +} |
| 131 | +}); |
| 132 | + |
97 | 133 | it("returns an empty string if body is empty", async () => { |
98 | 134 | let _body: string | undefined = "initial"; |
99 | 135 | app.use( |
|