From 317fc617c407687dd6ceaac6da0ed52486174791 Mon Sep 17 00:00:00 2001 From: arshiya tabasum Date: Mon, 20 Jul 2026 15:19:16 +0530 Subject: [PATCH 1/3] fix: accept a negative Set-Cookie Max-Age attribute Signed-off-by: arshiya tabasum --- lib/web/cookies/parse.js | 2 +- test/cookie/cookies.js | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/web/cookies/parse.js b/lib/web/cookies/parse.js index 51854822a8b..35eb2557030 100644 --- a/lib/web/cookies/parse.js +++ b/lib/web/cookies/parse.js @@ -196,7 +196,7 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) // 2. If the remainder of attribute-value contains a non-DIGIT // character, ignore the cookie-av. - if (!/^\d+$/.test(attributeValue)) { + if (!/^-?\d+$/.test(attributeValue)) { return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) } diff --git a/test/cookie/cookies.js b/test/cookie/cookies.js index 5167f8d64fd..9a389da2ee9 100644 --- a/test/cookie/cookies.js +++ b/test/cookie/cookies.js @@ -449,9 +449,22 @@ test('Set-Cookie parser', () => { name: 'Space', value: 'Cat', secure: true, - httpOnly: true + httpOnly: true, + maxAge: -1 }]) + for (const maxAge of ['-', '--1', '-1a', '+1', '']) { + headers = new Headers({ + 'set-cookie': `Space=Cat; Secure; HttpOnly; Max-Age=${maxAge}` + }) + assert.deepEqual(getSetCookies(headers), [{ + name: 'Space', + value: 'Cat', + secure: true, + httpOnly: true + }]) + } + headers = new Headers({ 'set-cookie': 'Space=Cat; Secure; HttpOnly; Max-Age=2; Domain=deno.land' }) From 4403160a9dc6d35c7c35abbf5370aaa5b994e1e7 Mon Sep 17 00:00:00 2001 From: arshiya tabasum Date: Tue, 11 Aug 2026 13:34:10 +0530 Subject: [PATCH 2/3] fix: check only the Max-Age remainder for non-DIGIT characters Signed-off-by: arshiya tabasum --- lib/web/cookies/parse.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/web/cookies/parse.js b/lib/web/cookies/parse.js index 35eb2557030..39da593672e 100644 --- a/lib/web/cookies/parse.js +++ b/lib/web/cookies/parse.js @@ -186,17 +186,19 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) // If the attribute-name case-insensitively matches the string "Max- // Age", the user agent MUST process the cookie-av as follows. - // 1. If the first character of the attribute-value is not a DIGIT or a - // "-" character, ignore the cookie-av. + // 1. If the first character of the attribute-value is neither a DIGIT, + // nor a "-" character followed by a DIGIT, ignore the cookie-av. const charCode = attributeValue.charCodeAt(0) + const startsWithDigit = charCode >= 48 && charCode <= 57 + const startsWithSignedDigit = attributeValue[0] === '-' && attributeValue.length > 1 - if ((charCode < 48 || charCode > 57) && attributeValue[0] !== '-') { + if (!startsWithDigit && !startsWithSignedDigit) { return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) } // 2. If the remainder of attribute-value contains a non-DIGIT // character, ignore the cookie-av. - if (!/^-?\d+$/.test(attributeValue)) { + if (/[^\d]/.test(attributeValue.slice(1))) { return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) } From 55df30d99e3f50b0c94e45cb0fcd0c42046635c6 Mon Sep 17 00:00:00 2001 From: arshiya tabasum Date: Wed, 12 Aug 2026 12:32:04 +0530 Subject: [PATCH 3/3] revert Max-Age step 1 comment to the pinned spec wording Signed-off-by: arshiya tabasum --- lib/web/cookies/parse.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/web/cookies/parse.js b/lib/web/cookies/parse.js index 39da593672e..da7454dda02 100644 --- a/lib/web/cookies/parse.js +++ b/lib/web/cookies/parse.js @@ -186,8 +186,8 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) // If the attribute-name case-insensitively matches the string "Max- // Age", the user agent MUST process the cookie-av as follows. - // 1. If the first character of the attribute-value is neither a DIGIT, - // nor a "-" character followed by a DIGIT, ignore the cookie-av. + // 1. If the first character of the attribute-value is not a DIGIT or a + // "-" character, ignore the cookie-av. const charCode = attributeValue.charCodeAt(0) const startsWithDigit = charCode >= 48 && charCode <= 57 const startsWithSignedDigit = attributeValue[0] === '-' && attributeValue.length > 1