diff --git a/tests/test_metadata_serialization.py b/tests/test_metadata_serialization.py index 9275b8b821..a313afffbf 100644 --- a/tests/test_metadata_serialization.py +++ b/tests/test_metadata_serialization.py @@ -330,6 +330,38 @@ def test_invalid_delegated_role_serialization(self, test_case_data: str): {"keyids": ["keyid2"], "name": "a", "paths": ["fn3"], "terminating": false, "threshold": 2} \ ] \ }', + "using empty string role name": '{"keys": { \ + "keyid1" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}}, \ + "roles": [ \ + {"keyids": ["keyid1"], "name": "", "terminating": true, "paths": ["fn1"], "threshold": 3}] \ + }', + "using root as delegate role name": '{"keys": { \ + "keyid1" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}}, \ + "roles": [ \ + {"keyids": ["keyid1"], "name": "root", "terminating": true, "paths": ["fn1"], "threshold": 3}] \ + }', + "using snapshot as delegate role name": '{"keys": { \ + "keyid1" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}}, \ + "roles": [ \ + {"keyids": ["keyid1"], "name": "snapshot", "terminating": true, "paths": ["fn1"], "threshold": 3}] \ + }', + "using targets as delegate role name": '{"keys": { \ + "keyid1" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}}, \ + "roles": [ \ + {"keyids": ["keyid1"], "name": "targets", "terminating": true, "paths": ["fn1"], "threshold": 3}] \ + }', + "using timestamp as delegate role name": '{"keys": { \ + "keyid1" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}}, \ + "roles": [ \ + {"keyids": ["keyid1"], "name": "timestamp", "terminating": true, "paths": ["fn1"], "threshold": 3}] \ + }', + "using valid and top-level role name": '{"keys": { \ + "keyid1" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}, \ + "keyid2" : {"keytype": "ed25519", "scheme": "ed25519", "keyval": {"public": "bar"}}}, \ + "roles": [ \ + {"keyids": ["keyid1"], "name": "b", "terminating": true, "paths": ["fn1"], "threshold": 3}, \ + {"keyids": ["keyid2"], "name": "root", "terminating": true, "paths": ["fn2"], "threshold": 4} ] \ + }', } @utils.run_sub_tests_with_dataset(invalid_delegations) diff --git a/tests/test_updater_with_simulator.py b/tests/test_updater_with_simulator.py index 25d536f456..53f316bdfd 100644 --- a/tests/test_updater_with_simulator.py +++ b/tests/test_updater_with_simulator.py @@ -137,7 +137,6 @@ def test_targets(self, test_case_data: Tuple[str, bytes, str]): def test_fishy_rolenames(self): roles_to_filenames = { "../a": "..%2Fa.json", - "": ".json", ".": "..json", "/": "%2F.json", "รถ": "%C3%B6.json", diff --git a/tuf/api/metadata.py b/tuf/api/metadata.py index 25f14fe772..b108898a8a 100644 --- a/tuf/api/metadata.py +++ b/tuf/api/metadata.py @@ -1213,6 +1213,13 @@ def __init__( unrecognized_fields: Optional[Mapping[str, Any]] = None, ): self.keys = keys + + for role in roles: + if not role or role in TOP_LEVEL_ROLE_NAMES: + raise ValueError( + "Delegated roles cannot be empty or use top-level role names" + ) + self.roles = roles self.unrecognized_fields = unrecognized_fields or {}