Skip to content

Commit cc067c8

Browse files
authored
Merge commit from fork
1 parent a586cd7 commit cc067c8

2 files changed

Lines changed: 55 additions & 5 deletions

File tree

src/utils/cookie.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ describe('Parse cookie', () => {
99
expect(cookie['tasty_cookie']).toBe('strawberry')
1010
})
1111

12+
it('Should trim only SP and HTAB around cookie pairs', () => {
13+
const cookieString = '\tyummy_cookie=choco;\t tasty_cookie = strawberry \t'
14+
const cookie: Cookie = parse(cookieString)
15+
expect(cookie['yummy_cookie']).toBe('choco')
16+
expect(cookie['tasty_cookie']).toBe('strawberry')
17+
})
18+
1219
it('Should parse quoted cookie values', () => {
1320
const cookieString =
1421
'yummy_cookie="choco"; tasty_cookie = " strawberry " ; best_cookie="%20sugar%20";'
@@ -81,6 +88,19 @@ describe('Parse cookie', () => {
8188
expect(cookie['best_cookie\\']).toBeUndefined()
8289
})
8390

91+
it('Should ignore NBSP-prefixed cookie names when parsing one cookie by name', () => {
92+
const cookieString = '\u00a0dummy-cookie=evil; dummy-cookie=victim'
93+
const cookie: Cookie = parse(cookieString, 'dummy-cookie')
94+
expect(cookie['dummy-cookie']).toBe('victim')
95+
})
96+
97+
it('Should not collapse NBSP-prefixed cookie names when parsing all cookies', () => {
98+
const cookieString = 'dummy-cookie=victim; \u00a0dummy-cookie=evil'
99+
const cookie: Cookie = parse(cookieString)
100+
expect(cookie['dummy-cookie']).toBe('victim')
101+
expect(cookie['\u00a0dummy-cookie']).toBeUndefined()
102+
})
103+
84104
it('Should parse signed cookies', async () => {
85105
const secret = 'secret ingredient'
86106
const cookieString =
@@ -159,6 +179,14 @@ describe('Parse cookie', () => {
159179
expect(cookie['tasty_cookie']).toBe('strawberry')
160180
expect(cookie['great_cookie']).toBeUndefined()
161181
})
182+
183+
it('Should ignore NBSP-prefixed signed cookie names when parsing one cookie by name', async () => {
184+
const secret = 'secret ingredient'
185+
const cookieString =
186+
'\u00a0dummy-cookie=evil.UdFR2rBpS1GsHfGlUiYyMIdqxqwuEgplyQIgTJgpGWY%3D; dummy-cookie=choco.UdFR2rBpS1GsHfGlUiYyMIdqxqwuEgplyQIgTJgpGWY%3D'
187+
const cookie: SignedCookie = await parseSigned(cookieString, secret, 'dummy-cookie')
188+
expect(cookie['dummy-cookie']).toBe('choco')
189+
})
162190
})
163191

164192
describe('Set cookie', () => {

src/utils/cookie.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,26 +76,48 @@ const validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/
7676
// (see: https://github.com/golang/go/issues/7243)
7777
const validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/
7878

79+
const trimCookieWhitespace = (value: string): string => {
80+
let start = 0
81+
let end = value.length
82+
83+
while (start < end) {
84+
const charCode = value.charCodeAt(start)
85+
if (charCode !== 0x20 && charCode !== 0x09) {
86+
break
87+
}
88+
start++
89+
}
90+
91+
while (end > start) {
92+
const charCode = value.charCodeAt(end - 1)
93+
if (charCode !== 0x20 && charCode !== 0x09) {
94+
break
95+
}
96+
end--
97+
}
98+
99+
return start === 0 && end === value.length ? value : value.slice(start, end)
100+
}
101+
79102
export const parse = (cookie: string, name?: string): Cookie => {
80103
if (name && cookie.indexOf(name) === -1) {
81104
// Fast-path: return immediately if the demanded-key is not in the cookie string
82105
return {}
83106
}
84-
const pairs = cookie.trim().split(';')
107+
const pairs = cookie.split(';')
85108
const parsedCookie: Cookie = {}
86-
for (let pairStr of pairs) {
87-
pairStr = pairStr.trim()
109+
for (const pairStr of pairs) {
88110
const valueStartPos = pairStr.indexOf('=')
89111
if (valueStartPos === -1) {
90112
continue
91113
}
92114

93-
const cookieName = pairStr.substring(0, valueStartPos).trim()
115+
const cookieName = trimCookieWhitespace(pairStr.substring(0, valueStartPos))
94116
if ((name && name !== cookieName) || !validCookieNameRegEx.test(cookieName)) {
95117
continue
96118
}
97119

98-
let cookieValue = pairStr.substring(valueStartPos + 1).trim()
120+
let cookieValue = trimCookieWhitespace(pairStr.substring(valueStartPos + 1))
99121
if (cookieValue.startsWith('"') && cookieValue.endsWith('"')) {
100122
cookieValue = cookieValue.slice(1, -1)
101123
}

0 commit comments

Comments
 (0)