Skip to content

Commit

Permalink
Merge pull request from GHSA-px8h-6qxv-m22q
Browse files Browse the repository at this point in the history
don't strip leading `=` when parsing cookie
  • Loading branch information
davidism authored Feb 14, 2023
2 parents 7c7ce5c + 8c2b4b8 commit cf275f4
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Unreleased
:issue:`2529`
- ``LimitedStream.read`` works correctly when wrapping a stream that may not return
the requested size in one ``read`` call. :issue:`2558`
- A cookie header that starts with ``=`` is treated as an empty key and discarded,
rather than stripping the leading ``==``.


Version 2.2.2
Expand Down
13 changes: 9 additions & 4 deletions src/werkzeug/_internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
_legal_cookie_chars_re = rb"[\w\d!#%&\'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]"
_cookie_re = re.compile(
rb"""
(?P<key>[^=;]+)
(?P<key>[^=;]*)
(?:\s*=\s*
(?P<val>
"(?:[^\\"]|\\.)*" |
Expand Down Expand Up @@ -382,16 +382,21 @@ def _cookie_parse_impl(b: bytes) -> t.Iterator[t.Tuple[bytes, bytes]]:
"""Lowlevel cookie parsing facility that operates on bytes."""
i = 0
n = len(b)
b += b";"

while i < n:
match = _cookie_re.search(b + b";", i)
match = _cookie_re.match(b, i)

if not match:
break

key = match.group("key").strip()
value = match.group("val") or b""
i = match.end(0)
key = match.group("key").strip()

if not key:
continue

value = match.group("val") or b""
yield key, _cookie_unquote(value)


Expand Down
4 changes: 0 additions & 4 deletions src/werkzeug/sansio/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,6 @@ def parse_cookie(
def _parse_pairs() -> t.Iterator[t.Tuple[str, str]]:
for key, val in _cookie_parse_impl(cookie): # type: ignore
key_str = _to_str(key, charset, errors, allow_none_charset=True)

if not key_str:
continue

val_str = _to_str(val, charset, errors, allow_none_charset=True)
yield key_str, val_str

Expand Down
4 changes: 3 additions & 1 deletion tests/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,8 @@ def test_is_resource_modified_for_range_requests(self):
def test_parse_cookie(self):
cookies = http.parse_cookie(
"dismiss-top=6; CP=null*; PHPSESSID=0a539d42abc001cdc762809248d4beed;"
'a=42; b="\\";"; ; fo234{=bar;blub=Blah; "__Secure-c"=d'
'a=42; b="\\";"; ; fo234{=bar;blub=Blah; "__Secure-c"=d;'
"==__Host-eq=bad;__Host-eq=good;"
)
assert cookies.to_dict() == {
"CP": "null*",
Expand All @@ -423,6 +424,7 @@ def test_parse_cookie(self):
"fo234{": "bar",
"blub": "Blah",
'"__Secure-c"': "d",
"__Host-eq": "good",
}

def test_dump_cookie(self):
Expand Down

0 comments on commit cf275f4

Please sign in to comment.