Skip to content

Commit 25efa44

Browse files
committed
fix(cookies): preserve values and parse SameSite strictly
Signed-off-by: Matteo Collina <hello@matteocollina.com> (cherry picked from commit 5655ea4)
1 parent f4c31d6 commit 25efa44

2 files changed

Lines changed: 59 additions & 23 deletions

File tree

lib/web/cookies/parse.js

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -275,32 +275,25 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {})
275275
// If the attribute-name case-insensitively matches the string
276276
// "SameSite", the user agent MUST process the cookie-av as follows:
277277

278-
// 1. Let enforcement be "Default".
279-
let enforcement = 'Default'
280-
281278
const attributeValueLowercase = attributeValue.toLowerCase()
282-
// 2. If cookie-av's attribute-value is a case-insensitive match for
283-
// "None", set enforcement to "None".
284-
if (attributeValueLowercase.includes('none')) {
285-
enforcement = 'None'
286-
}
287279

288-
// 3. If cookie-av's attribute-value is a case-insensitive match for
289-
// "Strict", set enforcement to "Strict".
290-
if (attributeValueLowercase.includes('strict')) {
291-
enforcement = 'Strict'
280+
// 1. If cookie-av's attribute-value is a case-insensitive match for
281+
// "None", append an attribute to the cookie-attribute-list with an
282+
// attribute-name of "SameSite" and an attribute-value of "None".
283+
if (attributeValueLowercase === 'none') {
284+
cookieAttributeList.sameSite = 'None'
285+
} else if (attributeValueLowercase === 'strict') {
286+
// 2. If cookie-av's attribute-value is a case-insensitive match for
287+
// "Strict", append an attribute to the cookie-attribute-list with
288+
// an attribute-name of "SameSite" and an attribute-value of
289+
// "Strict".
290+
cookieAttributeList.sameSite = 'Strict'
291+
} else if (attributeValueLowercase === 'lax') {
292+
// 3. If cookie-av's attribute-value is a case-insensitive match for
293+
// "Lax", append an attribute to the cookie-attribute-list with an
294+
// attribute-name of "SameSite" and an attribute-value of "Lax".
295+
cookieAttributeList.sameSite = 'Lax'
292296
}
293-
294-
// 4. If cookie-av's attribute-value is a case-insensitive match for
295-
// "Lax", set enforcement to "Lax".
296-
if (attributeValueLowercase.includes('lax')) {
297-
enforcement = 'Lax'
298-
}
299-
300-
// 5. Append an attribute to the cookie-attribute-list with an
301-
// attribute-name of "SameSite" and an attribute-value of
302-
// enforcement.
303-
cookieAttributeList.sameSite = enforcement
304297
} else {
305298
cookieAttributeList.unparsed ??= []
306299

test/cookie/cookies.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,49 @@ test('Set-Cookie parser', () => {
600600
assert.deepEqual(getSetCookies(headers), [])
601601
})
602602

603+
test('Set-Cookie parser does not percent-decode cookie values', () => {
604+
assert.deepEqual(
605+
getSetCookies(new Headers({
606+
'set-cookie': 'token=legit%0d%0aSet-Cookie:%20evil=injected%3B%20Path%3D/'
607+
})),
608+
[{
609+
name: 'token',
610+
value: 'legit%0d%0aSet-Cookie:%20evil=injected%3B%20Path%3D/'
611+
}]
612+
)
613+
614+
assert.deepEqual(getSetCookies(new Headers({
615+
'set-cookie': 'data=prefix%00suffix'
616+
})), [{
617+
name: 'data',
618+
value: 'prefix%00suffix'
619+
}])
620+
})
621+
622+
test('Set-Cookie parser only accepts exact SameSite values', () => {
623+
assert.deepEqual(getSetCookies(new Headers({
624+
'set-cookie': 'a=b; SameSite=none'
625+
})), [{
626+
name: 'a',
627+
value: 'b',
628+
sameSite: 'None'
629+
}])
630+
631+
assert.deepEqual(getSetCookies(new Headers({
632+
'set-cookie': 'a=b; SameSite=StrictLax'
633+
})), [{
634+
name: 'a',
635+
value: 'b'
636+
}])
637+
638+
assert.deepEqual(getSetCookies(new Headers({
639+
'set-cookie': 'a=b; SameSite=NoneOfYourBusiness'
640+
})), [{
641+
name: 'a',
642+
value: 'b'
643+
}])
644+
})
645+
603646
test('Cookie setCookie throws if headers is not of type Headers', () => {
604647
class Headers {
605648
[Symbol.toStringTag] = 'CustomHeaders'

0 commit comments

Comments
 (0)