diff options
-rw-r--r-- | std/http/cookie.ts | 14 | ||||
-rw-r--r-- | std/http/cookie_test.ts | 36 |
2 files changed, 49 insertions, 1 deletions
diff --git a/std/http/cookie.ts b/std/http/cookie.ts index 75d70f74e..f8025d328 100644 --- a/std/http/cookie.ts +++ b/std/http/cookie.ts @@ -32,11 +32,14 @@ export interface Cookie { export type SameSite = "Strict" | "Lax" | "None"; +const FIELD_CONTENT_REGEXP = /^(?=[\x20-\x7E]*$)[^()@<>,;:\\"\[\]?={}\s]+$/; + function toString(cookie: Cookie): string { if (!cookie.name) { return ""; } const out: string[] = []; + validateCookieName(cookie.name); out.push(`${cookie.name}=${cookie.value}`); // Fallback for invalid Set-Cookie @@ -80,6 +83,17 @@ function toString(cookie: Cookie): string { } /** + * Validate Cookie property. + * @param key Name of the cookie. + * @param value Value of the cookie. + */ +function validateCookieName(value: string | undefined | null): void { + if (value && !FIELD_CONTENT_REGEXP.test(value)) { + throw new TypeError(`Invalid cookie name: "${value}".`); + } +} + +/** * Parse the cookies of the Server Request * @param req An object which has a `headers` property */ diff --git a/std/http/cookie_test.ts b/std/http/cookie_test.ts index 0f7c68635..0f42a9381 100644 --- a/std/http/cookie_test.ts +++ b/std/http/cookie_test.ts @@ -1,7 +1,7 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. import { Response, ServerRequest } from "./server.ts"; import { deleteCookie, getCookies, setCookie } from "./cookie.ts"; -import { assert, assertEquals } from "../testing/asserts.ts"; +import { assert, assertEquals, assertThrows } from "../testing/asserts.ts"; Deno.test({ name: "Cookie parser", @@ -32,6 +32,40 @@ Deno.test({ }); Deno.test({ + name: "Cookie Name Validation", + fn(): void { + const res: Response = {}; + const tokens = [ + '"id"', + "id\t", + "i\td", + "i d", + "i;d", + "{id}", + "[id]", + '"', + "id\u0091", + ]; + res.headers = new Headers(); + tokens.forEach((name) => { + assertThrows( + (): void => { + setCookie(res, { + name, + value: "Cat", + httpOnly: true, + secure: true, + maxAge: 3, + }); + }, + Error, + 'Invalid cookie name: "' + name + '".', + ); + }); + }, +}); + +Deno.test({ name: "Cookie Delete", fn(): void { const res: Response = {}; |