Skip to content

Commit e8df9a0

Browse files
Validate header names as HTTP token characters
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 0ba6277 commit e8df9a0

4 files changed

Lines changed: 50 additions & 0 deletions

File tree

hyperbrowser/header_utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import json
2+
import re
23
from typing import Dict, Mapping, Optional, cast
34

45
from .exceptions import HyperbrowserError
56

7+
_INVALID_HEADER_NAME_CHARACTER_PATTERN = re.compile(r"[^!#$%&'*+\-.^_`|~0-9A-Za-z]")
8+
69

710
def normalize_headers(
811
headers: Optional[Mapping[str, str]],
@@ -24,6 +27,10 @@ def normalize_headers(
2427
normalized_key = key.strip()
2528
if not normalized_key:
2629
raise HyperbrowserError("header names must not be empty")
30+
if _INVALID_HEADER_NAME_CHARACTER_PATTERN.search(normalized_key):
31+
raise HyperbrowserError(
32+
"header names must contain only valid HTTP token characters"
33+
)
2734
if (
2835
"\n" in normalized_key
2936
or "\r" in normalized_key

tests/test_config.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,14 @@ def test_client_config_rejects_empty_header_name():
255255
ClientConfig(api_key="test-key", headers={" ": "value"})
256256

257257

258+
def test_client_config_rejects_invalid_header_name_characters():
259+
with pytest.raises(
260+
HyperbrowserError,
261+
match="header names must contain only valid HTTP token characters",
262+
):
263+
ClientConfig(api_key="test-key", headers={"X Trace": "value"})
264+
265+
258266
def test_client_config_rejects_newline_header_values():
259267
with pytest.raises(
260268
HyperbrowserError, match="headers must not contain newline characters"

tests/test_custom_headers.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ def test_sync_transport_rejects_empty_header_name():
4040
SyncTransport(api_key="test-key", headers={" ": "value"})
4141

4242

43+
def test_sync_transport_rejects_invalid_header_name_characters():
44+
with pytest.raises(
45+
HyperbrowserError,
46+
match="header names must contain only valid HTTP token characters",
47+
):
48+
SyncTransport(api_key="test-key", headers={"X Trace": "value"})
49+
50+
4351
def test_sync_transport_rejects_header_newline_values():
4452
with pytest.raises(
4553
HyperbrowserError, match="headers must not contain newline characters"
@@ -87,6 +95,14 @@ def test_async_transport_rejects_empty_header_name():
8795
AsyncTransport(api_key="test-key", headers={" ": "value"})
8896

8997

98+
def test_async_transport_rejects_invalid_header_name_characters():
99+
with pytest.raises(
100+
HyperbrowserError,
101+
match="header names must contain only valid HTTP token characters",
102+
):
103+
AsyncTransport(api_key="test-key", headers={"X Trace": "value"})
104+
105+
90106
def test_async_transport_rejects_header_newline_values():
91107
with pytest.raises(
92108
HyperbrowserError, match="headers must not contain newline characters"

tests/test_header_utils.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ def test_normalize_headers_rejects_empty_header_name():
2525
)
2626

2727

28+
def test_normalize_headers_rejects_invalid_header_name_characters():
29+
with pytest.raises(
30+
HyperbrowserError,
31+
match="header names must contain only valid HTTP token characters",
32+
):
33+
normalize_headers(
34+
{"X Trace Id": "value"},
35+
mapping_error_message="headers must be a mapping of string pairs",
36+
)
37+
38+
2839
def test_normalize_headers_rejects_duplicate_names_after_normalization():
2940
with pytest.raises(
3041
HyperbrowserError,
@@ -73,6 +84,14 @@ def test_parse_headers_env_json_rejects_non_mapping_payload():
7384
parse_headers_env_json('["bad"]')
7485

7586

87+
def test_parse_headers_env_json_rejects_invalid_header_name_characters():
88+
with pytest.raises(
89+
HyperbrowserError,
90+
match="header names must contain only valid HTTP token characters",
91+
):
92+
parse_headers_env_json('{"X Trace Id":"abc123"}')
93+
94+
7695
def test_normalize_headers_rejects_control_characters():
7796
with pytest.raises(
7897
HyperbrowserError, match="headers must not contain control characters"

0 commit comments

Comments
 (0)