diff --git a/stix2/test/v21/test_external_reference.py b/stix2/test/v21/test_external_reference.py index d192a11..f5a3e23 100644 --- a/stix2/test/v21/test_external_reference.py +++ b/stix2/test/v21/test_external_reference.py @@ -120,3 +120,13 @@ def test_external_reference_source_required(): assert excinfo.value.cls == stix2.v21.ExternalReference assert excinfo.value.properties == ["source_name"] + + +def test_external_reference_bad_hash(): + with pytest.raises(stix2.exceptions.InvalidValueError): + stix2.v21.ExternalReference( + source_name="ACME Threat Intel", + hashes={ + "SHA-123": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + ) \ No newline at end of file diff --git a/stix2/v21/common.py b/stix2/v21/common.py index cf3a3b3..ac8daf1 100644 --- a/stix2/v21/common.py +++ b/stix2/v21/common.py @@ -4,6 +4,7 @@ from collections import OrderedDict from ..base import _STIXBase from ..custom import _custom_marking_builder +from ..exceptions import InvalidValueError from ..markings import _MarkingsMixin from ..markings.utils import check_tlp_marking from ..properties import ( @@ -28,10 +29,26 @@ class ExternalReference(_STIXBase): ('external_id', StringProperty()), ]) + # This is hash-algorithm-ov + _LEGAL_HASHES = { + "MD5", "SHA-1", "SHA-256", "SHA-512", "SHA3-256", "SHA3-512", "SSDEEP", + "TLSH", + } + def _check_object_constraints(self): super(ExternalReference, self)._check_object_constraints() self._check_at_least_one_property(['description', 'external_id', 'url']) + if "hashes" in self: + if any( + hash_ not in self._LEGAL_HASHES + for hash_ in self["hashes"] + ): + raise InvalidValueError( + ExternalReference, "hashes", + "Hash algorithm names must be members of hash-algorithm-ov", + ) + class KillChainPhase(_STIXBase): # TODO: Add link