diff --git a/packages/dexpace-sdk-core/src/dexpace/sdk/core/http/common/etag.py b/packages/dexpace-sdk-core/src/dexpace/sdk/core/http/common/etag.py index 41797d9..1828f6b 100644 --- a/packages/dexpace-sdk-core/src/dexpace/sdk/core/http/common/etag.py +++ b/packages/dexpace-sdk-core/src/dexpace/sdk/core/http/common/etag.py @@ -103,7 +103,7 @@ def parse(cls, raw: str) -> Self: # RFC 7232 §2.3: etagc = %x21 / %x23-7E / obs-text. Everything at or # below SP (0x20) and DEL (0x7F) is outside the entity-tag character # set; obs-text (0x80-0xFF) stays permitted. - if any(ord(ch) <= 0x20 or ord(ch) == 0x7F for ch in value): + if any(ord(ch) <= 0x20 or ord(ch) == 0x7F or ord(ch) > 0xFF for ch in value): raise ValueError(f"Invalid ETag: illegal character in {raw!r}") return cls(value=value, weak=weak) diff --git a/packages/dexpace-sdk-core/tests/http/test_etag.py b/packages/dexpace-sdk-core/tests/http/test_etag.py index 7b991d7..ad3c127 100644 --- a/packages/dexpace-sdk-core/tests/http/test_etag.py +++ b/packages/dexpace-sdk-core/tests/http/test_etag.py @@ -58,6 +58,13 @@ def test_parse_embedded_space_raises() -> None: ETag.parse('"a b"') +def test_parse_above_obs_text_raises() -> None: + # RFC 7232 §2.3: obs-text tops out at 0xFF; codepoints above + # that (e.g. U+20AC) are not valid entity-tag characters. + with pytest.raises(ValueError): + ETag.parse('"a€b"') + + def test_parse_empty_strong_etag_raises() -> None: with pytest.raises(ValueError, match="empty"): ETag.parse('""')