|
4 | 4 | setCookie, |
5 | 5 | getChunkedCookie, |
6 | 6 | setChunkedCookie, |
| 7 | + deleteChunkedCookie, |
7 | 8 | } from "../src/utils/cookie.ts"; |
8 | 9 | import { describeMatrix } from "./_setup.ts"; |
9 | 10 |
|
@@ -153,6 +154,42 @@ describeMatrix("cookies", (t, { it, expect, describe }) => { |
153 | 154 | }); |
154 | 155 | }); |
155 | 156 |
|
| 157 | + describe("chunked cookie DoS protection", () => { |
| 158 | + it("setChunkedCookie ignores excessively large chunk count from request cookie", async () => { |
| 159 | + t.app.get("/", (event) => { |
| 160 | + // This should NOT loop 999999 times |
| 161 | + setChunkedCookie(event, "session", "newvalue", { |
| 162 | + chunkMaxLength: 5, |
| 163 | + }); |
| 164 | + return "200"; |
| 165 | + }); |
| 166 | + const result = await t.fetch("/", { |
| 167 | + headers: { |
| 168 | + Cookie: "session=__chunked__999999", |
| 169 | + }, |
| 170 | + }); |
| 171 | + expect(await result.text()).toBe("200"); |
| 172 | + // Should only have the new cookie set, no massive cleanup |
| 173 | + expect(result.headers.getSetCookie().length).toBeLessThan(10); |
| 174 | + }); |
| 175 | + |
| 176 | + it("deleteChunkedCookie ignores excessively large chunk count from request cookie", async () => { |
| 177 | + t.app.get("/", (event) => { |
| 178 | + // This should NOT loop 999999 times |
| 179 | + deleteChunkedCookie(event, "session"); |
| 180 | + return "200"; |
| 181 | + }); |
| 182 | + const result = await t.fetch("/", { |
| 183 | + headers: { |
| 184 | + Cookie: "session=__chunked__999999", |
| 185 | + }, |
| 186 | + }); |
| 187 | + expect(await result.text()).toBe("200"); |
| 188 | + // Should only delete the main cookie, not 999999 chunks |
| 189 | + expect(result.headers.getSetCookie().length).toBeLessThan(10); |
| 190 | + }); |
| 191 | + }); |
| 192 | + |
156 | 193 | describe("setChunkedCookie", () => { |
157 | 194 | it("can set-cookie with setChunkedCookie", async () => { |
158 | 195 | t.app.get("/", (event) => { |
|
0 commit comments