Skip to content

Commit 10d9dad

Browse files
committed
fix: reject crit header in unprotected headers
1 parent 408c865 commit 10d9dad

File tree

4 files changed

+13
-5
lines changed

4 files changed

+13
-5
lines changed

src/joserfc/_rfc7515/json.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
FlattenedJSONSerialization,
1313
)
1414
from .registry import JWSRegistry
15+
from ..registry import reject_unprotected_crit_header
1516
from ..util import (
1617
json_b64encode,
1718
json_b64decode,
@@ -65,6 +66,7 @@ def sign_flattened_json(
6566
def sign_json_member(
6667
payload_segment: bytes, member: HeaderMember, registry: JWSRegistry, find_key: FindKey
6768
) -> JSONSignatureDict:
69+
reject_unprotected_crit_header(member.header)
6870
headers = member.headers()
6971
registry.check_header(headers)
7072
alg = registry.get_alg(headers["alg"])
@@ -131,6 +133,7 @@ def verify_signature(
131133
registry: JWSRegistry,
132134
find_key: FindKey,
133135
) -> bool:
136+
reject_unprotected_crit_header(member.header)
134137
headers = member.headers()
135138
registry.check_header(headers)
136139
alg = registry.get_alg(headers["alg"])

src/joserfc/jwe.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from .jwa import setup_jwe_algorithms
2626
from .jwk import Key, KeySet, ECKey, OKPKey, KeyFlexible, guess_key
2727
from .util import to_bytes
28-
from .registry import Header
28+
from .registry import Header, reject_unprotected_crit_header
2929

3030
__all__ = [
3131
# types
@@ -195,6 +195,7 @@ def encrypt_json(
195195
elif registry is None:
196196
registry = default_registry
197197

198+
reject_unprotected_crit_header(obj.unprotected)
198199
for recipient in obj.recipients:
199200
if sender_key and not recipient.sender_key:
200201
recipient.sender_key = _guess_sender_key(recipient, sender_key, True)
@@ -232,6 +233,7 @@ def decrypt_json(
232233
elif registry is None:
233234
registry = default_registry
234235

236+
reject_unprotected_crit_header(data.get("unprotected"))
235237
if "recipients" in data:
236238
general_obj = extract_general_json(data) # type: ignore[arg-type]
237239
_attach_recipient_keys(general_obj.recipients, private_key, sender_key)

src/joserfc/registry.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,8 @@ def check_crit_header(registry: HeaderRegistryDict, header: Header) -> None:
211211
raise MissingCritHeaderError(",".join(missing_crit_headers))
212212
elif unsupported_crit_headers:
213213
raise UnsupportedHeaderError(f"Unsupported {unsupported_crit_headers} in header")
214+
215+
216+
def reject_unprotected_crit_header(unprotected: Header) -> None:
217+
if unprotected and "crit" in unprotected:
218+
raise UnsupportedHeaderError("'crit' header MUST be protected header")

tests/jws/test_rfc7797.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
BadSignatureError,
66
InvalidHeaderValueError,
77
MissingCritHeaderError,
8+
UnsupportedHeaderError,
89
)
910
from joserfc.util import to_bytes
1011
from joserfc.jws import HeaderDict
@@ -70,10 +71,7 @@ def test_compact_use_registry(self):
7071
def test_json_without_protected_header(self):
7172
header = {"alg": "HS256", "b64": False, "crit": ["b64"]}
7273
member: HeaderDict = {"header": header}
73-
value = jws.serialize_json(member, "hello", default_key)
74-
obj = jws.deserialize_json(value, default_key)
75-
self.assertTrue(obj.flattened)
76-
self.assertEqual(obj.headers(), header)
74+
self.assertRaises(UnsupportedHeaderError, jws.serialize_json, member, "hello", default_key)
7775

7876
def test_general_json(self):
7977
member: HeaderDict = {"protected": {"alg": "HS256"}}

0 commit comments

Comments
 (0)