From ee3e4d29e623028c7ec7aa5c6a40df217de33ef5 Mon Sep 17 00:00:00 2001 From: Roberto Prevato Date: Tue, 30 Dec 2025 09:17:07 +0100 Subject: [PATCH 1/4] Fix #646 --- CHANGELOG.md | 6 ++++++ blacksheep/cookies.py | 2 +- blacksheep/cookies.pyx | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aaf44839..5fc3f4b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.4.6] - 2025-12-?? + +- Fix [#646](https://github.com/Neoteroi/BlackSheep/issues/646), +- Modify the `Cookie` `repr` to not include the value in full, as it can contain secrets + that would leak in logs. + ## [2.4.5] - 2025-11-15 :mount_fuji: - Fix [#636](https://github.com/Neoteroi/BlackSheep/issues/636). diff --git a/blacksheep/cookies.py b/blacksheep/cookies.py index 32886ba0..cee2bac9 100644 --- a/blacksheep/cookies.py +++ b/blacksheep/cookies.py @@ -99,7 +99,7 @@ def __eq__(self, other): return NotImplemented def __repr__(self) -> str: - return f"" + return f"" def split_value(raw_value: bytes, separator: bytes) -> tuple[bytes, bytes]: diff --git a/blacksheep/cookies.pyx b/blacksheep/cookies.pyx index 7b279000..2b4fb792 100644 --- a/blacksheep/cookies.pyx +++ b/blacksheep/cookies.pyx @@ -96,7 +96,7 @@ cdef class Cookie: return NotImplemented def __repr__(self): - return f'' + return f"" cdef tuple split_value(bytes raw_value, bytes separator): From 00cf15d9b4df736cc1a4bf08e5498ae7523e0014 Mon Sep 17 00:00:00 2001 From: Roberto Prevato Date: Tue, 30 Dec 2025 09:47:08 +0100 Subject: [PATCH 2/4] Complete #646 --- CHANGELOG.md | 1 + tests/test_cookies.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fc3f4b0..fac0a2b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix [#646](https://github.com/Neoteroi/BlackSheep/issues/646), - Modify the `Cookie` `repr` to not include the value in full, as it can contain secrets that would leak in logs. +- Improve type annotations for several modules, by @tyzhnenko. ## [2.4.5] - 2025-11-15 :mount_fuji: diff --git a/tests/test_cookies.py b/tests/test_cookies.py index 055c6d06..7f258a05 100644 --- a/tests/test_cookies.py +++ b/tests/test_cookies.py @@ -267,3 +267,21 @@ def test_raise_for_value_exceeding_length(): with pytest.raises(CookieValueExceedsMaximumLength): Cookie("crash", "A" * 5000) + + +@pytest.mark.parametrize( + "name,value,expected_repr", + [ + ("session", "abc123xyz", ""), + ("token", "verylongvalue", ""), + ("id", "12345", ""), + ("short", "ab", ""), + ("tiny", "x", ""), + ("empty", "", ""), + ("exact", "123", ""), + ("special", "a!@#$%^&*()", ""), + ], +) +def test_cookie_repr(name, value, expected_repr): + cookie = Cookie(name, value) + assert repr(cookie) == expected_repr From 3c8edd963a53acfdac415b7da89942e29fee0619 Mon Sep 17 00:00:00 2001 From: Roberto Prevato Date: Tue, 30 Dec 2025 09:52:40 +0100 Subject: [PATCH 3/4] Add more tests for cookies --- tests/test_cookies.py | 110 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/tests/test_cookies.py b/tests/test_cookies.py index 7f258a05..f82e960b 100644 --- a/tests/test_cookies.py +++ b/tests/test_cookies.py @@ -285,3 +285,113 @@ def test_raise_for_value_exceeding_length(): def test_cookie_repr(name, value, expected_repr): cookie = Cookie(name, value) assert repr(cookie) == expected_repr + + +def test_cookie_equality_with_string(): + cookie = Cookie("session", "abc123") + assert cookie == "abc123" + assert not (cookie == "different") + + +def test_cookie_equality_with_bytes(): + cookie = Cookie("session", "abc123") + assert cookie == b"abc123" + assert not (cookie == b"different") + + +def test_cookie_equality_with_cookie(): + cookie1 = Cookie("session", "abc123") + cookie2 = Cookie("session", "abc123") + cookie3 = Cookie("session", "different") + cookie4 = Cookie("different", "abc123") + + assert cookie1 == cookie2 + assert not (cookie1 == cookie3) + assert not (cookie1 == cookie4) + + +def test_cookie_equality_with_other_types(): + cookie = Cookie("session", "abc123") + assert cookie.__eq__(123) == NotImplemented + assert cookie.__eq__(None) == NotImplemented + assert cookie.__eq__([]) == NotImplemented + + +def test_cookie_clone(): + original = Cookie( + "session", + "abc123", + expires=datetime(2025, 12, 31, 23, 59, 59), + domain="example.com", + path="/app", + http_only=True, + secure=True, + max_age=3600, + same_site=CookieSameSiteMode.STRICT, + ) + + cloned = original.clone() + + assert cloned is not original + assert cloned.name == original.name + assert cloned.value == original.value + assert cloned.expires == original.expires + assert cloned.domain == original.domain + assert cloned.path == original.path + assert cloned.http_only == original.http_only + assert cloned.secure == original.secure + assert cloned.max_age == original.max_age + assert cloned.same_site == original.same_site + + +def test_cookie_clone_independence(): + original = Cookie("session", "original") + cloned = original.clone() + + cloned.value = "modified" + + assert original.value == "original" + assert cloned.value == "modified" + + +def test_cookie_empty_name_raises_error(): + with pytest.raises(ValueError, match="A cookie name is required"): + Cookie("", "value") + + +def test_cookie_name_setter_validation(): + cookie = Cookie("valid", "value") + + with pytest.raises(ValueError, match="A cookie name is required"): + cookie.name = "" + + +def test_cookie_value_setter(): + cookie = Cookie("session", "initial") + assert cookie.value == "initial" + + cookie.value = "updated" + assert cookie.value == "updated" + + +def test_cookie_value_setter_exceeds_length(): + cookie = Cookie("session", "short") + + with pytest.raises(CookieValueExceedsMaximumLength): + cookie.value = "A" * 5000 + + +def test_cookie_value_with_multibyte_characters(): + # Test that byte length is checked, not character length + # Each emoji is typically 4 bytes + value = "🍪" * 1025 # Should exceed 4096 bytes + + with pytest.raises(CookieValueExceedsMaximumLength): + Cookie("emoji", value) + + +def test_cookie_value_multibyte_within_limit(): + # 1000 characters of 2-byte chars = 2000 bytes, within limit + value = "ñ" * 1000 + cookie = Cookie("multibyte", value) + assert cookie.value == value From 3b3c654a75e9e9f424466610f53331ca75e4028b Mon Sep 17 00:00:00 2001 From: Roberto Prevato Date: Tue, 30 Dec 2025 10:05:30 +0100 Subject: [PATCH 4/4] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fac0a2b4..35e450f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2.4.6] - 2025-12-?? -- Fix [#646](https://github.com/Neoteroi/BlackSheep/issues/646), +- Fix [#646](https://github.com/Neoteroi/BlackSheep/issues/646). - Modify the `Cookie` `repr` to not include the value in full, as it can contain secrets that would leak in logs. - Improve type annotations for several modules, by @tyzhnenko.