Skip to content
4 changes: 4 additions & 0 deletions Doc/library/http.cookies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ Cookie Objects
for k, v in rawdata.items():
cookie[k] = v

.. versionchanged:: 3.9
:meth:`load` now correctly throws :class:`CookieError` instead of
silently ignoring erroneous data.


.. _morsel-objects:

Expand Down
15 changes: 12 additions & 3 deletions Lib/http/cookies.py
Original file line number Diff line number Diff line change
Expand Up @@ -565,21 +565,30 @@ def __parse_string(self, str, patt=_CookiePattern):
elif key.lower() in Morsel._reserved:
if not morsel_seen:
# Invalid cookie string
return
raise CookieError('Cookie begins with Morsel reserved'
'attribute %r' % (key,))
if value is None:
if key.lower() in Morsel._flags:
parsed_items.append((TYPE_ATTRIBUTE, key, True))
else:
# Invalid cookie string
return
raise CookieError('Morsel reserved attribute %r must '
'have a value.' % (key,))
else:
parsed_items.append((TYPE_ATTRIBUTE, key, _unquote(value)))
elif value is not None:
parsed_items.append((TYPE_KEYVALUE, key, self.value_decode(value)))
morsel_seen = True
else:
# Invalid cookie string
return
raise CookieError('No value found for key %r' % (key,))

# Invalid tailing data, make sure it's not whitespace.
if i < n:
tail = str[i:].rstrip()
if tail:
raise CookieError('Invalid tailing data %r' % (tail,))


# The cookie string is valid, apply it.
M = None # current morsel
Expand Down
10 changes: 6 additions & 4 deletions Lib/test/test_http_cookies.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,16 @@ def test_quoted_meta(self):

def test_invalid_cookies(self):
# Accepting these could be a security issue
# Issue 40002: Error inconsistency, changed to raise CookieError.
C = cookies.SimpleCookie()
for s in (']foo=x', '[foo=x', 'blah]foo=x', 'blah[foo=x',
'Set-Cookie: foo=bar', 'Set-Cookie: foo',
'foo=bar; baz', 'baz; foo=bar',
'secure;foo=bar', 'Version=1;foo=bar'):
C.load(s)
self.assertEqual(dict(C), {})
self.assertEqual(C.output(), '')
'secure;foo=bar', 'Version=1;foo=bar',
'invalid\x00=cookie', 'Path=/acme;',
'foo=bar;Version;'):
with self.assertRaises(cookies.CookieError):
C.load(s)

def test_pickle(self):
rawdata = 'Customer="WILE_E_COYOTE"; Path=/acme; Version=1'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fixed :func:`http.cookies.BaseCookie.load()` to consistently throw errors on
invalid cookies. Patch by Bar Harel.