Repository: oasis-open/cti-python-stix2
Pull request #269 (2019-06-14 22:23:20)

Update id properties
Updates IDProperty and ReferenceProperty to support both stix 2.0 and 2.1 rules regarding identifiers.   Behavior is chosen via a new "spec_version" constructor parameter.  Also changes all uses of IDProperty and ReferenceProperty to specify a particular spec_version.


Patch:
diff --git a/stix2/__init__.py b/stix2/__init__.py
index 3bedec8..4498c8b 100644
--- a/stix2/__init__.py
+++ b/stix2/__init__.py
@@ -28,6 +28,8 @@
 
 # flake8: noqa
 
+DEFAULT_VERSION = '2.1'  # Default version will always be the latest STIX 2.X version
+
 from .confidence import scales
 from .core import _collect_stix2_mappings, parse, parse_observable
 from .datastore import CompositeDataSource
@@ -64,5 +66,3 @@ from .v20 import *  # This import will always be the latest STIX 2.X version
 from .version import __version__
 
 _collect_stix2_mappings()
-
-DEFAULT_VERSION = '2.0'  # Default version will always be the latest STIX 2.X version
diff --git a/stix2/markings/utils.py b/stix2/markings/utils.py
index 4b4841c..d8bbf1d 100644
--- a/stix2/markings/utils.py
+++ b/stix2/markings/utils.py
@@ -39,7 +39,7 @@ def _validate_selector(obj, selector):
 
 
 def _get_marking_id(marking):
-    if type(marking).__name__ is 'MarkingDefinition':  # avoid circular import
+    if type(marking).__name__ == 'MarkingDefinition':  # avoid circular import
         return marking.id
     return marking
 
diff --git a/stix2/properties.py b/stix2/properties.py
index 24549aa..8e0066c 100644
--- a/stix2/properties.py
+++ b/stix2/properties.py
@@ -11,29 +11,70 @@ import uuid
 from six import string_types, text_type
 from stix2patterns.validator import run_validator
 
+import stix2
+
 from .base import _STIXBase
 from .core import STIX2_OBJ_MAPS, parse, parse_observable
 from .exceptions import CustomContentError, DictionaryKeyError
 from .utils import _get_dict, get_class_hierarchy_names, parse_into_datetime
 
-# This uses the regular expression for a RFC 4122, Version 4 UUID. In the
-# 8-4-4-4-12 hexadecimal representation, the first hex digit of the third
-# component must be a 4, and the first hex digit of the fourth component
-# must be 8, 9, a, or b (10xx bit pattern).
-ID_REGEX = re.compile(
-    r"^[a-z0-9][a-z0-9-]+[a-z0-9]--"  # object type
-    "[0-9a-fA-F]{8}-"
-    "[0-9a-fA-F]{4}-"
-    "4[0-9a-fA-F]{3}-"
-    "[89abAB][0-9a-fA-F]{3}-"
-    "[0-9a-fA-F]{12}$",
-)
-
 ERROR_INVALID_ID = (
-    "not a valid STIX identifier, must match <object-type>--<UUIDv4>"
+    "not a valid STIX identifier, must match <object-type>--<UUID>: {}"
 )
 
 
+def _check_uuid(uuid_str, spec_version):
+    """
+    Check whether the given UUID string is valid with respect to the given STIX
+    spec version.  STIX 2.0 requires UUIDv4; 2.1 only requires the RFC 4122
+    variant.
+
+    :param uuid_str: A UUID as a string
+    :param spec_version: The STIX spec version
+    :return: True if the UUID is valid, False if not
+    :raises ValueError: If uuid_str is malformed
+    """
+    uuid_obj = uuid.UUID(uuid_str)
+
+    ok = uuid_obj.variant == uuid.RFC_4122
+    if ok and spec_version == "2.0":
+        ok = uuid_obj.version == 4
+
+    return ok
+
+
+def _validate_id(id_, spec_version, required_prefix):
+    """
+    Check the STIX identifier for correctness, raise an exception if there are
+    errors.
+
+    :param id_: The STIX identifier
+    :param spec_version: The STIX specification version to use
+    :param required_prefix: The required prefix on the identifier, if any.
+        This function doesn't add a "--" suffix to the prefix, so callers must
+        add it if it is important.  Pass None to skip the prefix check.
+    :raises ValueError: If there are any errors with the identifier
+    """
+    if required_prefix:
+        if not id_.startswith(required_prefix):
+            raise ValueError("must start with '{}'.".format(required_prefix))
+
+    try:
+        if required_prefix:
+            uuid_part = id_[len(required_prefix):]
+        else:
+            idx = id_.index("--")
+            uuid_part = id_[idx+2:]
+
+        result = _check_uuid(uuid_part, spec_version)
+    except ValueError:
+        # replace their ValueError with ours
+        raise ValueError(ERROR_INVALID_ID.format(id_))
+
+    if not result:
+        raise ValueError(ERROR_INVALID_ID.format(id_))
+
+
 class Property(object):
     """Represent a property of STIX data type.
 
@@ -143,7 +184,7 @@ class ListProperty(Property):
 
             if type(self.contained) is EmbeddedObjectProperty:
                 obj_type = self.contained.type
-            elif type(self.contained).__name__ is "STIXObjectProperty":
+            elif type(self.contained).__name__ == "STIXObjectProperty":
                 # ^ this way of checking doesn't require a circular import
                 # valid is already an instance of a python-stix2 class; no need
                 # to turn it into a dictionary and then pass it to the class
@@ -185,15 +226,13 @@ class TypeProperty(Property):
 
 class IDProperty(Property):
 
-    def __init__(self, type):
+    def __init__(self, type, spec_version=stix2.DEFAULT_VERSION):
         self.required_prefix = type + "--"
+        self.spec_version = spec_version
         super(IDProperty, self).__init__()
 
     def clean(self, value):
-        if not value.startswith(self.required_prefix):
-            raise ValueError("must start with '{}'.".format(self.required_prefix))
-        if not ID_REGEX.match(value):
-            raise ValueError(ERROR_INVALID_ID)
+        _validate_id(value, self.spec_version, self.required_prefix)
         return value
 
     def default(self):
@@ -282,7 +321,7 @@ class TimestampProperty(Property):
 
 class DictionaryProperty(Property):
 
-    def __init__(self, spec_version='2.0', **kwargs):
+    def __init__(self, spec_version=stix2.DEFAULT_VERSION, **kwargs):
         self.spec_version = spec_version
         super(DictionaryProperty, self).__init__(**kwargs)
 
@@ -366,22 +405,21 @@ class HexProperty(Property):
 
 class ReferenceProperty(Property):
 
-    def __init__(self, type=None, **kwargs):
+    def __init__(self, type=None, spec_version=stix2.DEFAULT_VERSION, **kwargs):
         """
         references sometimes must be to a specific object type
         """
-        self.type = type
+        self.required_prefix = type + "--" if type else None
+        self.spec_version = spec_version
         super(ReferenceProperty, self).__init__(**kwargs)
 
     def clean(self, value):
         if isinstance(value, _STIXBase):
             value = value.id
         value = str(value)
-        if self.type:
-            if not value.startswith(self.type):
-                raise ValueError("must start with '{}'.".format(self.type))
-        if not ID_REGEX.match(value):
-            raise ValueError(ERROR_INVALID_ID)
+
+        _validate_id(value, self.spec_version, self.required_prefix)
+
         return value
 
 
@@ -449,7 +487,7 @@ class ObservableProperty(Property):
     """Property for holding Cyber Observable Objects.
     """
 
-    def __init__(self, spec_version='2.0', allow_custom=False, *args, **kwargs):
+    def __init__(self, spec_version=stix2.DEFAULT_VERSION, allow_custom=False, *args, **kwargs):
         self.allow_custom = allow_custom
         self.spec_version = spec_version
         super(ObservableProperty, self).__init__(*args, **kwargs)
@@ -484,7 +522,7 @@ class ExtensionsProperty(DictionaryProperty):
     """Property for representing extensions on Observable objects.
     """
 
-    def __init__(self, spec_version='2.0', allow_custom=False, enclosing_type=None, required=False):
+    def __init__(self, spec_version=stix2.DEFAULT_VERSION, allow_custom=False, enclosing_type=None, required=False):
         self.allow_custom = allow_custom
         self.enclosing_type = enclosing_type
         super(ExtensionsProperty, self).__init__(spec_version=spec_version, required=required)
@@ -525,7 +563,7 @@ class ExtensionsProperty(DictionaryProperty):
 
 class STIXObjectProperty(Property):
 
-    def __init__(self, spec_version='2.0', allow_custom=False, *args, **kwargs):
+    def __init__(self, spec_version=stix2.DEFAULT_VERSION, allow_custom=False, *args, **kwargs):
         self.allow_custom = allow_custom
         self.spec_version = spec_version
         super(STIXObjectProperty, self).__init__(*args, **kwargs)
diff --git a/stix2/v20/bundle.py b/stix2/v20/bundle.py
index 76386ef..fe6b62e 100644
--- a/stix2/v20/bundle.py
+++ b/stix2/v20/bundle.py
@@ -16,11 +16,11 @@ class Bundle(_STIXBase):
     _type = 'bundle'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
+        ('id', IDProperty(_type, spec_version='2.0')),
         # Not technically correct: STIX 2.0 spec doesn't say spec_version must
         # have this value, but it's all we support for now.
         ('spec_version', StringProperty(fixed='2.0')),
-        ('objects', ListProperty(STIXObjectProperty)),
+        ('objects', ListProperty(STIXObjectProperty(spec_version="2.0"))),
     ])
 
     def __init__(self, *args, **kwargs):
diff --git a/stix2/v20/common.py b/stix2/v20/common.py
index afd7812..b8149a2 100644
--- a/stix2/v20/common.py
+++ b/stix2/v20/common.py
@@ -48,7 +48,7 @@ class GranularMarking(_STIXBase):
     """
 
     _properties = OrderedDict([
-        ('marking_ref', ReferenceProperty(required=True, type='marking-definition')),
+        ('marking_ref', ReferenceProperty(required=True, spec_version='2.0', type='marking-definition')),
         ('selectors', ListProperty(SelectorProperty, required=True)),
     ])
 
@@ -103,11 +103,11 @@ class MarkingDefinition(_STIXBase, _MarkingsMixin):
     _type = 'marking-definition'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
         ('definition_type', StringProperty(required=True)),
         ('definition', MarkingProperty(required=True)),
diff --git a/stix2/v20/observables.py b/stix2/v20/observables.py
index 0e7c4a0..ba28214 100644
--- a/stix2/v20/observables.py
+++ b/stix2/v20/observables.py
@@ -31,7 +31,7 @@ class Artifact(_Observable):
         ('payload_bin', BinaryProperty()),
         ('url', StringProperty()),
         ('hashes', HashesProperty()),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
     def _check_object_constraints(self):
@@ -51,7 +51,7 @@ class AutonomousSystem(_Observable):
         ('number', IntegerProperty(required=True)),
         ('name', StringProperty()),
         ('rir', StringProperty()),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -70,7 +70,7 @@ class Directory(_Observable):
         ('modified', TimestampProperty()),
         ('accessed', TimestampProperty()),
         ('contains_refs', ListProperty(ObjectReferenceProperty(valid_types=['file', 'directory']))),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -84,7 +84,7 @@ class DomainName(_Observable):
         ('type', TypeProperty(_type)),
         ('value', StringProperty(required=True)),
         ('resolves_to_refs', ListProperty(ObjectReferenceProperty(valid_types=['ipv4-addr', 'ipv6-addr', 'domain-name']))),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -99,7 +99,7 @@ class EmailAddress(_Observable):
         ('value', StringProperty(required=True)),
         ('display_name', StringProperty()),
         ('belongs_to_ref', ObjectReferenceProperty(valid_types='user-account')),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -138,11 +138,11 @@ class EmailMessage(_Observable):
         ('bcc_refs', ListProperty(ObjectReferenceProperty(valid_types='email-addr'))),
         ('subject', StringProperty()),
         ('received_lines', ListProperty(StringProperty)),
-        ('additional_header_fields', DictionaryProperty()),
+        ('additional_header_fields', DictionaryProperty(spec_version="2.0")),
         ('body', StringProperty()),
         ('body_multipart', ListProperty(EmbeddedObjectProperty(type=EmailMIMEComponent))),
         ('raw_email_ref', ObjectReferenceProperty(valid_types='artifact')),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
     def _check_object_constraints(self):
@@ -199,7 +199,7 @@ class PDFExt(_Extension):
     _properties = OrderedDict([
         ('version', StringProperty()),
         ('is_optimized', BooleanProperty()),
-        ('document_info_dict', DictionaryProperty()),
+        ('document_info_dict', DictionaryProperty(spec_version="2.0")),
         ('pdfid0', StringProperty()),
         ('pdfid1', StringProperty()),
     ])
@@ -216,7 +216,7 @@ class RasterImageExt(_Extension):
         ('image_width', IntegerProperty()),
         ('bits_per_pixel', IntegerProperty()),
         ('image_compression_algorithm', StringProperty()),
-        ('exif_tags', DictionaryProperty()),
+        ('exif_tags', DictionaryProperty(spec_version="2.0")),
     ])
 
 
@@ -323,7 +323,7 @@ class File(_Observable):
         ('decryption_key', StringProperty()),
         ('contains_refs', ListProperty(ObjectReferenceProperty)),
         ('content_ref', ObjectReferenceProperty(valid_types='artifact')),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
     def _check_object_constraints(self):
@@ -343,7 +343,7 @@ class IPv4Address(_Observable):
         ('value', StringProperty(required=True)),
         ('resolves_to_refs', ListProperty(ObjectReferenceProperty(valid_types='mac-addr'))),
         ('belongs_to_refs', ListProperty(ObjectReferenceProperty(valid_types='autonomous-system'))),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -358,7 +358,7 @@ class IPv6Address(_Observable):
         ('value', StringProperty(required=True)),
         ('resolves_to_refs', ListProperty(ObjectReferenceProperty(valid_types='mac-addr'))),
         ('belongs_to_refs', ListProperty(ObjectReferenceProperty(valid_types='autonomous-system'))),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -371,7 +371,7 @@ class MACAddress(_Observable):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('value', StringProperty(required=True)),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -384,7 +384,7 @@ class Mutex(_Observable):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('name', StringProperty(required=True)),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -398,7 +398,7 @@ class HTTPRequestExt(_Extension):
         ('request_method', StringProperty(required=True)),
         ('request_value', StringProperty(required=True)),
         ('request_version', StringProperty()),
-        ('request_header', DictionaryProperty()),
+        ('request_header', DictionaryProperty(spec_version="2.0")),
         ('message_body_length', IntegerProperty()),
         ('message_body_data_ref', ObjectReferenceProperty(valid_types='artifact')),
     ])
@@ -449,7 +449,7 @@ class SocketExt(_Extension):
                 "PF_NETROM",
             ]),
         ),
-        ('options', DictionaryProperty()),
+        ('options', DictionaryProperty(spec_version="2.0")),
         (
             'socket_type', EnumProperty(allowed=[
                 "SOCK_STREAM",
@@ -496,12 +496,12 @@ class NetworkTraffic(_Observable):
         ('dst_byte_count', IntegerProperty()),
         ('src_packets', IntegerProperty()),
         ('dst_packets', IntegerProperty()),
-        ('ipfix', DictionaryProperty()),
+        ('ipfix', DictionaryProperty(spec_version="2.0")),
         ('src_payload_ref', ObjectReferenceProperty(valid_types='artifact')),
         ('dst_payload_ref', ObjectReferenceProperty(valid_types='artifact')),
         ('encapsulates_refs', ListProperty(ObjectReferenceProperty(valid_types='network-traffic'))),
         ('encapsulates_by_ref', ObjectReferenceProperty(valid_types='network-traffic')),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
     def _check_object_constraints(self):
@@ -521,7 +521,7 @@ class WindowsProcessExt(_Extension):
         ('priority', StringProperty()),
         ('owner_sid', StringProperty()),
         ('window_title', StringProperty()),
-        ('startup_info', DictionaryProperty()),
+        ('startup_info', DictionaryProperty(spec_version="2.0")),
     ])
 
 
@@ -584,13 +584,13 @@ class Process(_Observable):
         ('cwd', StringProperty()),
         ('arguments', ListProperty(StringProperty)),
         ('command_line', StringProperty()),
-        ('environment_variables', DictionaryProperty()),
+        ('environment_variables', DictionaryProperty(spec_version="2.0")),
         ('opened_connection_refs', ListProperty(ObjectReferenceProperty(valid_types='network-traffic'))),
         ('creator_user_ref', ObjectReferenceProperty(valid_types='user-account')),
         ('binary_ref', ObjectReferenceProperty(valid_types='file')),
         ('parent_ref', ObjectReferenceProperty(valid_types='process')),
         ('child_refs', ListProperty(ObjectReferenceProperty('process'))),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
     def _check_object_constraints(self):
@@ -621,7 +621,7 @@ class Software(_Observable):
         ('languages', ListProperty(StringProperty)),
         ('vendor', StringProperty()),
         ('version', StringProperty()),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -634,7 +634,7 @@ class URL(_Observable):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('value', StringProperty(required=True)),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -673,7 +673,7 @@ class UserAccount(_Observable):
         ('password_last_changed', TimestampProperty()),
         ('account_first_login', TimestampProperty()),
         ('account_last_login', TimestampProperty()),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -720,7 +720,7 @@ class WindowsRegistryKey(_Observable):
         ('modified', TimestampProperty()),
         ('creator_user_ref', ObjectReferenceProperty(valid_types='user-account')),
         ('number_of_subkeys', IntegerProperty()),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
     @property
@@ -776,7 +776,7 @@ class X509Certificate(_Observable):
         ('subject_public_key_modulus', StringProperty()),
         ('subject_public_key_exponent', IntegerProperty()),
         ('x509_v3_extensions', EmbeddedObjectProperty(type=X509V3ExtenstionsType)),
-        ('extensions', ExtensionsProperty(enclosing_type=_type)),
+        ('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=_type)),
     ])
 
 
@@ -798,7 +798,7 @@ def CustomObservable(type='x-custom-observable', properties=None):
         _properties = list(itertools.chain.from_iterable([
             [('type', TypeProperty(type))],
             properties,
-            [('extensions', ExtensionsProperty(enclosing_type=type))],
+            [('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=type))],
         ]))
         return _custom_observable_builder(cls, type, _properties, '2.0')
     return wrapper
diff --git a/stix2/v20/sdo.py b/stix2/v20/sdo.py
index cd99e69..3fd3a84 100644
--- a/stix2/v20/sdo.py
+++ b/stix2/v20/sdo.py
@@ -22,8 +22,8 @@ class AttackPattern(STIXDomainObject):
     _type = 'attack-pattern'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -32,7 +32,7 @@ class AttackPattern(STIXDomainObject):
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -45,8 +45,8 @@ class Campaign(STIXDomainObject):
     _type = 'campaign'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -58,7 +58,7 @@ class Campaign(STIXDomainObject):
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -71,8 +71,8 @@ class CourseOfAction(STIXDomainObject):
     _type = 'course-of-action'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -80,7 +80,7 @@ class CourseOfAction(STIXDomainObject):
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -93,8 +93,8 @@ class Identity(STIXDomainObject):
     _type = 'identity'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -105,7 +105,7 @@ class Identity(STIXDomainObject):
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -118,8 +118,8 @@ class Indicator(STIXDomainObject):
     _type = 'indicator'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty()),
@@ -131,7 +131,7 @@ class Indicator(STIXDomainObject):
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty, required=True)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -144,8 +144,8 @@ class IntrusionSet(STIXDomainObject):
     _type = 'intrusion-set'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -160,7 +160,7 @@ class IntrusionSet(STIXDomainObject):
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -173,8 +173,8 @@ class Malware(STIXDomainObject):
     _type = 'malware'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -183,7 +183,7 @@ class Malware(STIXDomainObject):
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty, required=True)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -196,18 +196,18 @@ class ObservedData(STIXDomainObject):
     _type = 'observed-data'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('first_observed', TimestampProperty(required=True)),
         ('last_observed', TimestampProperty(required=True)),
         ('number_observed', IntegerProperty(min=1, max=999999999, required=True)),
-        ('objects', ObservableProperty(required=True)),
+        ('objects', ObservableProperty(spec_version="2.0", required=True)),
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -226,18 +226,18 @@ class Report(STIXDomainObject):
     _type = 'report'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
         ('description', StringProperty()),
         ('published', TimestampProperty(required=True)),
-        ('object_refs', ListProperty(ReferenceProperty, required=True)),
+        ('object_refs', ListProperty(ReferenceProperty(spec_version='2.0'), required=True)),
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty, required=True)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -250,8 +250,8 @@ class ThreatActor(STIXDomainObject):
     _type = 'threat-actor'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -267,7 +267,7 @@ class ThreatActor(STIXDomainObject):
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty, required=True)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -280,8 +280,8 @@ class Tool(STIXDomainObject):
     _type = 'tool'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -291,7 +291,7 @@ class Tool(STIXDomainObject):
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty, required=True)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -304,8 +304,8 @@ class Vulnerability(STIXDomainObject):
     _type = 'vulnerability'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -313,7 +313,7 @@ class Vulnerability(STIXDomainObject):
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -351,8 +351,8 @@ def CustomObject(type='x-custom-type', properties=None):
         _properties = list(itertools.chain.from_iterable([
             [
                 ('type', TypeProperty(type)),
-                ('id', IDProperty(type)),
-                ('created_by_ref', ReferenceProperty(type='identity')),
+                ('id', IDProperty(type, spec_version='2.0')),
+                ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
                 ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
                 ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
             ],
@@ -361,7 +361,7 @@ def CustomObject(type='x-custom-type', properties=None):
                 ('revoked', BooleanProperty(default=lambda: False)),
                 ('labels', ListProperty(StringProperty)),
                 ('external_references', ListProperty(ExternalReference)),
-                ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+                ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
                 ('granular_markings', ListProperty(GranularMarking)),
             ],
             sorted([x for x in properties if x[0].startswith('x_')], key=lambda x: x[0]),
diff --git a/stix2/v20/sro.py b/stix2/v20/sro.py
index dbf6812..f450003 100644
--- a/stix2/v20/sro.py
+++ b/stix2/v20/sro.py
@@ -19,18 +19,18 @@ class Relationship(STIXRelationshipObject):
     _type = 'relationship'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('relationship_type', StringProperty(required=True)),
         ('description', StringProperty()),
-        ('source_ref', ReferenceProperty(required=True)),
-        ('target_ref', ReferenceProperty(required=True)),
+        ('source_ref', ReferenceProperty(spec_version='2.0', required=True)),
+        ('target_ref', ReferenceProperty(spec_version='2.0', required=True)),
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -58,21 +58,21 @@ class Sighting(STIXRelationshipObject):
     _type = 'sighting'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.0')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.0')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('first_seen', TimestampProperty()),
         ('last_seen', TimestampProperty()),
         ('count', IntegerProperty(min=0, max=999999999)),
-        ('sighting_of_ref', ReferenceProperty(required=True)),
-        ('observed_data_refs', ListProperty(ReferenceProperty(type='observed-data'))),
-        ('where_sighted_refs', ListProperty(ReferenceProperty(type='identity'))),
+        ('sighting_of_ref', ReferenceProperty(spec_version='2.0', required=True)),
+        ('observed_data_refs', ListProperty(ReferenceProperty(type='observed-data', spec_version='2.0'))),
+        ('where_sighted_refs', ListProperty(ReferenceProperty(type='identity', spec_version='2.0'))),
         ('summary', BooleanProperty(default=lambda: False)),
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.0'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
diff --git a/stix2/v21/bundle.py b/stix2/v21/bundle.py
index c9e083a..c84058e 100644
--- a/stix2/v21/bundle.py
+++ b/stix2/v21/bundle.py
@@ -17,7 +17,7 @@ class Bundle(_STIXBase):
     _type = 'bundle'
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
-        ('id', IDProperty(_type)),
+        ('id', IDProperty(_type, spec_version='2.1')),
         ('objects', ListProperty(STIXObjectProperty(spec_version='2.1'))),
     ])
 
diff --git a/stix2/v21/common.py b/stix2/v21/common.py
index 0aded3b..110529e 100644
--- a/stix2/v21/common.py
+++ b/stix2/v21/common.py
@@ -53,7 +53,7 @@ class GranularMarking(_STIXBase):
 
     _properties = OrderedDict([
         ('lang', StringProperty()),
-        ('marking_ref', ReferenceProperty(type='marking-definition')),
+        ('marking_ref', ReferenceProperty(type='marking-definition', spec_version='2.1')),
         ('selectors', ListProperty(SelectorProperty, required=True)),
     ])
 
@@ -72,11 +72,11 @@ class LanguageContent(_STIXBase):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
-        ('object_ref', ReferenceProperty(required=True)),
+        ('object_ref', ReferenceProperty(spec_version='2.1', required=True)),
         # TODO: 'object_modified' it MUST be an exact match for the modified time of the STIX Object (SRO or SDO) being referenced.
         ('object_modified', TimestampProperty(required=True, precision='millisecond')),
         # TODO: 'contents' https://docs.google.com/document/d/1ShNq4c3e1CkfANmD9O--mdZ5H0O_GLnjN28a_yrEaco/edit#heading=h.cfz5hcantmvx
@@ -85,7 +85,7 @@ class LanguageContent(_STIXBase):
         ('labels', ListProperty(StringProperty)),
         ('confidence', IntegerProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -144,10 +144,10 @@ class MarkingDefinition(_STIXBase, _MarkingsMixin):
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
         ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW)),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
         ('definition_type', StringProperty(required=True)),
         ('definition', MarkingProperty(required=True)),
diff --git a/stix2/v21/sdo.py b/stix2/v21/sdo.py
index 8e5cdc2..ffdc5e1 100644
--- a/stix2/v21/sdo.py
+++ b/stix2/v21/sdo.py
@@ -24,8 +24,8 @@ class AttackPattern(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -36,7 +36,7 @@ class AttackPattern(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -51,8 +51,8 @@ class Campaign(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -66,7 +66,7 @@ class Campaign(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -91,8 +91,8 @@ class CourseOfAction(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -106,7 +106,7 @@ class CourseOfAction(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -129,8 +129,8 @@ class Identity(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -144,7 +144,7 @@ class Identity(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -159,8 +159,8 @@ class Indicator(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty()),
@@ -175,7 +175,7 @@ class Indicator(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -200,8 +200,8 @@ class IntrusionSet(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -218,7 +218,7 @@ class IntrusionSet(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -243,8 +243,8 @@ class Location(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('description', StringProperty()),
@@ -262,7 +262,7 @@ class Location(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -286,8 +286,8 @@ class Malware(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -299,7 +299,7 @@ class Malware(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -314,8 +314,8 @@ class Note(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('abstract', StringProperty()),
@@ -327,7 +327,7 @@ class Note(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -342,8 +342,8 @@ class ObservedData(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('first_observed', TimestampProperty(required=True)),
@@ -355,7 +355,7 @@ class ObservedData(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -390,8 +390,8 @@ class Opinion(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('explanation', StringProperty()),
@@ -413,7 +413,7 @@ class Opinion(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -428,8 +428,8 @@ class Report(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -442,7 +442,7 @@ class Report(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -457,8 +457,8 @@ class ThreatActor(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -477,7 +477,7 @@ class ThreatActor(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -492,8 +492,8 @@ class Tool(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -506,7 +506,7 @@ class Tool(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -521,8 +521,8 @@ class Vulnerability(STIXDomainObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('name', StringProperty(required=True)),
@@ -532,7 +532,7 @@ class Vulnerability(STIXDomainObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -571,8 +571,8 @@ def CustomObject(type='x-custom-type', properties=None):
             [
                 ('type', TypeProperty(type)),
                 ('spec_version', StringProperty(fixed='2.1')),
-                ('id', IDProperty(type)),
-                ('created_by_ref', ReferenceProperty(type='identity')),
+                ('id', IDProperty(type, spec_version='2.1')),
+                ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
                 ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
                 ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
             ],
@@ -583,7 +583,7 @@ def CustomObject(type='x-custom-type', properties=None):
                 ('confidence', IntegerProperty()),
                 ('lang', StringProperty()),
                 ('external_references', ListProperty(ExternalReference)),
-                ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+                ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
                 ('granular_markings', ListProperty(GranularMarking)),
             ],
             sorted([x for x in properties if x[0].startswith('x_')], key=lambda x: x[0]),
diff --git a/stix2/v21/sro.py b/stix2/v21/sro.py
index f947b2e..144df59 100644
--- a/stix2/v21/sro.py
+++ b/stix2/v21/sro.py
@@ -21,14 +21,14 @@ class Relationship(STIXRelationshipObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('relationship_type', StringProperty(required=True)),
         ('description', StringProperty()),
-        ('source_ref', ReferenceProperty(required=True)),
-        ('target_ref', ReferenceProperty(required=True)),
+        ('source_ref', ReferenceProperty(spec_version='2.1', required=True)),
+        ('target_ref', ReferenceProperty(spec_version='2.1', required=True)),
         ('start_time', TimestampProperty()),
         ('stop_time', TimestampProperty()),
         ('revoked', BooleanProperty(default=lambda: False)),
@@ -36,7 +36,7 @@ class Relationship(STIXRelationshipObject):
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 
@@ -76,23 +76,23 @@ class Sighting(STIXRelationshipObject):
     _properties = OrderedDict([
         ('type', TypeProperty(_type)),
         ('spec_version', StringProperty(fixed='2.1')),
-        ('id', IDProperty(_type)),
-        ('created_by_ref', ReferenceProperty(type='identity')),
+        ('id', IDProperty(_type, spec_version='2.1')),
+        ('created_by_ref', ReferenceProperty(type='identity', spec_version='2.1')),
         ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
         ('first_seen', TimestampProperty()),
         ('last_seen', TimestampProperty()),
         ('count', IntegerProperty(min=0, max=999999999)),
-        ('sighting_of_ref', ReferenceProperty(required=True)),
-        ('observed_data_refs', ListProperty(ReferenceProperty(type='observed-data'))),
-        ('where_sighted_refs', ListProperty(ReferenceProperty(type='identity'))),
+        ('sighting_of_ref', ReferenceProperty(spec_version='2.1', required=True)),
+        ('observed_data_refs', ListProperty(ReferenceProperty(type='observed-data', spec_version='2.1'))),
+        ('where_sighted_refs', ListProperty(ReferenceProperty(type='identity', spec_version='2.1'))),
         ('summary', BooleanProperty()),
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty)),
         ('confidence', IntegerProperty()),
         ('lang', StringProperty()),
         ('external_references', ListProperty(ExternalReference)),
-        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
+        ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition', spec_version='2.1'))),
         ('granular_markings', ListProperty(GranularMarking)),
     ])
 


Test patch:
diff --git a/stix2/test/v20/test_indicator.py b/stix2/test/v20/test_indicator.py
index f8c3a91..5194142 100644
--- a/stix2/test/v20/test_indicator.py
+++ b/stix2/test/v20/test_indicator.py
@@ -112,8 +112,6 @@ def test_indicator_created_ref_invalid_format():
 
     assert excinfo.value.cls == stix2.v20.Indicator
     assert excinfo.value.prop_name == "created_by_ref"
-    assert excinfo.value.reason == "must start with 'identity'."
-    assert str(excinfo.value) == "Invalid value for Indicator 'created_by_ref': must start with 'identity'."
 
 
 def test_indicator_revoked_invalid():
diff --git a/stix2/test/v20/test_observed_data.py b/stix2/test/v20/test_observed_data.py
index 41a80d6..cbdd394 100644
--- a/stix2/test/v20/test_observed_data.py
+++ b/stix2/test/v20/test_observed_data.py
@@ -1095,11 +1095,11 @@ def test_process_example_empty_error():
 
 def test_process_example_empty_with_extensions():
     with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
-            stix2.v20.Process(
-                extensions={
-                    "windows-process-ext": {},
-                },
-            )
+        stix2.v20.Process(
+            extensions={
+                "windows-process-ext": {},
+            },
+        )
 
     assert excinfo.value.cls == stix2.v20.WindowsProcessExt
     properties_of_extension = list(stix2.v20.WindowsProcessExt._properties.keys())
@@ -1127,13 +1127,13 @@ def test_process_example_windows_process_ext():
 
 def test_process_example_windows_process_ext_empty():
     with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
-            stix2.v20.Process(
-                pid=1221,
-                name="gedit-bin",
-                extensions={
-                    "windows-process-ext": {},
-                },
-            )
+        stix2.v20.Process(
+            pid=1221,
+            name="gedit-bin",
+            extensions={
+                "windows-process-ext": {},
+            },
+        )
 
     assert excinfo.value.cls == stix2.v20.WindowsProcessExt
     properties_of_extension = list(stix2.v20.WindowsProcessExt._properties.keys())
@@ -1142,7 +1142,7 @@ def test_process_example_windows_process_ext_empty():
 
 def test_process_example_extensions_empty():
     with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
-            stix2.v20.Process(extensions={})
+        stix2.v20.Process(extensions={})
 
     assert excinfo.value.cls == stix2.v20.Process
     assert excinfo.value.prop_name == 'extensions'
diff --git a/stix2/test/v20/test_properties.py b/stix2/test/v20/test_properties.py
index 24c1c99..4305e57 100644
--- a/stix2/test/v20/test_properties.py
+++ b/stix2/test/v20/test_properties.py
@@ -5,7 +5,7 @@ import pytest
 import stix2
 from stix2.exceptions import AtLeastOnePropertyError, DictionaryKeyError
 from stix2.properties import (
-    ERROR_INVALID_ID, BinaryProperty, BooleanProperty, DictionaryProperty,
+    BinaryProperty, BooleanProperty, DictionaryProperty,
     EmbeddedObjectProperty, EnumProperty, ExtensionsProperty, FloatProperty,
     HashesProperty, HexProperty, IDProperty, IntegerProperty, ListProperty,
     Property, ReferenceProperty, STIXObjectProperty, StringProperty,
@@ -89,7 +89,7 @@ def test_type_property():
     assert prop.clean(prop.default())
 
 
-ID_PROP = IDProperty('my-type')
+ID_PROP = IDProperty('my-type', spec_version="2.0")
 MY_ID = 'my-type--232c9d3f-49fc-4440-bb01-607f638778e7'
 
 
@@ -127,7 +127,7 @@ CONSTANT_IDS.extend(constants.RELATIONSHIP_IDS)
 @pytest.mark.parametrize("value", CONSTANT_IDS)
 def test_id_property_valid_for_type(value):
     type = value.split('--', 1)[0]
-    assert IDProperty(type=type).clean(value) == value
+    assert IDProperty(type=type, spec_version="2.0").clean(value) == value
 
 
 def test_id_property_wrong_type():
@@ -147,9 +147,8 @@ def test_id_property_wrong_type():
     ],
 )
 def test_id_property_not_a_valid_hex_uuid(value):
-    with pytest.raises(ValueError) as excinfo:
+    with pytest.raises(ValueError):
         ID_PROP.clean(value)
-    assert str(excinfo.value) == ERROR_INVALID_ID
 
 
 def test_id_property_default():
@@ -275,7 +274,7 @@ def test_boolean_property_invalid(value):
 
 
 def test_reference_property():
-    ref_prop = ReferenceProperty()
+    ref_prop = ReferenceProperty(spec_version="2.0")
 
     assert ref_prop.clean("my-type--00000000-0000-4000-8000-000000000000")
     with pytest.raises(ValueError):
@@ -286,6 +285,16 @@ def test_reference_property():
         ref_prop.clean("my-type--00000000-0000-0000-0000-000000000000")
 
 
+def test_reference_property_specific_type():
+    ref_prop = ReferenceProperty("my-type", spec_version="2.0")
+
+    with pytest.raises(ValueError):
+        ref_prop.clean("not-my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf")
+
+    assert ref_prop.clean("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf") == \
+        "my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf"
+
+
 @pytest.mark.parametrize(
     "value", [
         '2017-01-01T12:34:56Z',
@@ -329,7 +338,7 @@ def test_hex_property():
     ],
 )
 def test_dictionary_property_valid(d):
-    dict_prop = DictionaryProperty()
+    dict_prop = DictionaryProperty(spec_version="2.0")
     assert dict_prop.clean(d)
 
 
@@ -350,7 +359,7 @@ def test_dictionary_property_valid(d):
     ],
 )
 def test_dictionary_property_invalid_key(d):
-    dict_prop = DictionaryProperty()
+    dict_prop = DictionaryProperty(spec_version="2.0")
 
     with pytest.raises(DictionaryKeyError) as excinfo:
         dict_prop.clean(d[0])
@@ -373,7 +382,7 @@ def test_dictionary_property_invalid_key(d):
     ],
 )
 def test_dictionary_property_invalid(d):
-    dict_prop = DictionaryProperty()
+    dict_prop = DictionaryProperty(spec_version="2.0")
 
     with pytest.raises(ValueError) as excinfo:
         dict_prop.clean(d[0])
@@ -383,7 +392,7 @@ def test_dictionary_property_invalid(d):
 def test_property_list_of_dictionary():
     @stix2.v20.CustomObject(
         'x-new-obj', [
-            ('property1', ListProperty(DictionaryProperty(), required=True)),
+            ('property1', ListProperty(DictionaryProperty(spec_version="2.0"), required=True)),
         ],
     )
     class NewObj():
@@ -449,7 +458,7 @@ def test_enum_property_invalid():
 
 
 def test_extension_property_valid():
-    ext_prop = ExtensionsProperty(enclosing_type='file')
+    ext_prop = ExtensionsProperty(spec_version="2.0", enclosing_type='file')
     assert ext_prop({
         'windows-pebinary-ext': {
             'pe_type': 'exe',
@@ -466,13 +475,13 @@ def test_extension_property_valid():
     ],
 )
 def test_extension_property_invalid(data):
-    ext_prop = ExtensionsProperty(enclosing_type='file')
+    ext_prop = ExtensionsProperty(spec_version="2.0", enclosing_type='file')
     with pytest.raises(ValueError):
         ext_prop.clean(data)
 
 
 def test_extension_property_invalid_type():
-    ext_prop = ExtensionsProperty(enclosing_type='indicator')
+    ext_prop = ExtensionsProperty(spec_version="2.0", enclosing_type='indicator')
     with pytest.raises(ValueError) as excinfo:
         ext_prop.clean(
             {
diff --git a/stix2/test/v20/test_report.py b/stix2/test/v20/test_report.py
index 072fc95..fc4f288 100644
--- a/stix2/test/v20/test_report.py
+++ b/stix2/test/v20/test_report.py
@@ -87,8 +87,6 @@ def test_report_example_objects_in_object_refs_with_bad_id():
 
     assert excinfo.value.cls == stix2.v20.Report
     assert excinfo.value.prop_name == "object_refs"
-    assert excinfo.value.reason == stix2.properties.ERROR_INVALID_ID
-    assert str(excinfo.value) == "Invalid value for Report 'object_refs': " + stix2.properties.ERROR_INVALID_ID
 
 
 @pytest.mark.parametrize(
diff --git a/stix2/test/v20/test_sighting.py b/stix2/test/v20/test_sighting.py
index e93ca7e..f1d40c5 100644
--- a/stix2/test/v20/test_sighting.py
+++ b/stix2/test/v20/test_sighting.py
@@ -59,8 +59,6 @@ def test_sighting_bad_where_sighted_refs():
 
     assert excinfo.value.cls == stix2.v20.Sighting
     assert excinfo.value.prop_name == "where_sighted_refs"
-    assert excinfo.value.reason == "must start with 'identity'."
-    assert str(excinfo.value) == "Invalid value for Sighting 'where_sighted_refs': must start with 'identity'."
 
 
 def test_sighting_type_must_be_sightings():
@@ -69,8 +67,6 @@ def test_sighting_type_must_be_sightings():
 
     assert excinfo.value.cls == stix2.v20.Sighting
     assert excinfo.value.prop_name == "type"
-    assert excinfo.value.reason == "must equal 'sighting'."
-    assert str(excinfo.value) == "Invalid value for Sighting 'type': must equal 'sighting'."
 
 
 def test_invalid_kwarg_to_sighting():
diff --git a/stix2/test/v21/test_indicator.py b/stix2/test/v21/test_indicator.py
index 628bdff..a54ea62 100644
--- a/stix2/test/v21/test_indicator.py
+++ b/stix2/test/v21/test_indicator.py
@@ -116,8 +116,6 @@ def test_indicator_created_ref_invalid_format():
 
     assert excinfo.value.cls == stix2.v21.Indicator
     assert excinfo.value.prop_name == "created_by_ref"
-    assert excinfo.value.reason == "must start with 'identity'."
-    assert str(excinfo.value) == "Invalid value for Indicator 'created_by_ref': must start with 'identity'."
 
 
 def test_indicator_revoked_invalid():
diff --git a/stix2/test/v21/test_observed_data.py b/stix2/test/v21/test_observed_data.py
index 5a5881a..e729f60 100644
--- a/stix2/test/v21/test_observed_data.py
+++ b/stix2/test/v21/test_observed_data.py
@@ -1073,9 +1073,9 @@ def test_process_example_empty_error():
 
 def test_process_example_empty_with_extensions():
     with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
-            stix2.v21.Process(extensions={
-                "windows-process-ext": {},
-            })
+        stix2.v21.Process(extensions={
+            "windows-process-ext": {},
+        })
 
     assert excinfo.value.cls == stix2.v21.WindowsProcessExt
     properties_of_extension = list(stix2.v21.WindowsProcessExt._properties.keys())
@@ -1102,12 +1102,12 @@ def test_process_example_windows_process_ext():
 
 def test_process_example_windows_process_ext_empty():
     with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
-            stix2.v21.Process(
-                pid=1221,
-                extensions={
-                    "windows-process-ext": {},
-                },
-            )
+        stix2.v21.Process(
+            pid=1221,
+            extensions={
+                "windows-process-ext": {},
+            },
+        )
 
     assert excinfo.value.cls == stix2.v21.WindowsProcessExt
     properties_of_extension = list(stix2.v21.WindowsProcessExt._properties.keys())
@@ -1116,7 +1116,7 @@ def test_process_example_windows_process_ext_empty():
 
 def test_process_example_extensions_empty():
     with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
-            stix2.v21.Process(extensions={})
+        stix2.v21.Process(extensions={})
 
     assert excinfo.value.cls == stix2.v21.Process
     assert excinfo.value.prop_name == 'extensions'
diff --git a/stix2/test/v21/test_properties.py b/stix2/test/v21/test_properties.py
index 611ec5e..3e4ee92 100644
--- a/stix2/test/v21/test_properties.py
+++ b/stix2/test/v21/test_properties.py
@@ -1,11 +1,9 @@
-import uuid
-
 import pytest
 
 import stix2
 from stix2.exceptions import AtLeastOnePropertyError, DictionaryKeyError
 from stix2.properties import (
-    ERROR_INVALID_ID, BinaryProperty, BooleanProperty, DictionaryProperty,
+    BinaryProperty, BooleanProperty, DictionaryProperty,
     EmbeddedObjectProperty, EnumProperty, ExtensionsProperty, FloatProperty,
     HashesProperty, HexProperty, IDProperty, IntegerProperty, ListProperty,
     Property, ReferenceProperty, StringProperty, TimestampProperty,
@@ -89,7 +87,7 @@ def test_type_property():
     assert prop.clean(prop.default())
 
 
-ID_PROP = IDProperty('my-type')
+ID_PROP = IDProperty('my-type', spec_version="2.1")
 MY_ID = 'my-type--232c9d3f-49fc-4440-bb01-607f638778e7'
 
 
@@ -127,7 +125,7 @@ CONSTANT_IDS.extend(constants.RELATIONSHIP_IDS)
 @pytest.mark.parametrize("value", CONSTANT_IDS)
 def test_id_property_valid_for_type(value):
     type = value.split('--', 1)[0]
-    assert IDProperty(type=type).clean(value) == value
+    assert IDProperty(type=type, spec_version="2.1").clean(value) == value
 
 
 def test_id_property_wrong_type():
@@ -139,17 +137,13 @@ def test_id_property_wrong_type():
 @pytest.mark.parametrize(
     "value", [
         'my-type--foo',
-        # Not a v4 UUID
+        # Not a RFC 4122 UUID
         'my-type--00000000-0000-0000-0000-000000000000',
-        'my-type--' + str(uuid.uuid1()),
-        'my-type--' + str(uuid.uuid3(uuid.NAMESPACE_DNS, "example.org")),
-        'my-type--' + str(uuid.uuid5(uuid.NAMESPACE_DNS, "example.org")),
     ],
 )
 def test_id_property_not_a_valid_hex_uuid(value):
-    with pytest.raises(ValueError) as excinfo:
+    with pytest.raises(ValueError):
         ID_PROP.clean(value)
-    assert str(excinfo.value) == ERROR_INVALID_ID
 
 
 def test_id_property_default():
@@ -275,17 +269,27 @@ def test_boolean_property_invalid(value):
 
 
 def test_reference_property():
-    ref_prop = ReferenceProperty()
+    ref_prop = ReferenceProperty(spec_version="2.1")
 
     assert ref_prop.clean("my-type--00000000-0000-4000-8000-000000000000")
     with pytest.raises(ValueError):
         ref_prop.clean("foo")
 
-    # This is not a valid V4 UUID
+    # This is not a valid RFC 4122 UUID
     with pytest.raises(ValueError):
         ref_prop.clean("my-type--00000000-0000-0000-0000-000000000000")
 
 
+def test_reference_property_specific_type():
+    ref_prop = ReferenceProperty("my-type", spec_version="2.1")
+
+    with pytest.raises(ValueError):
+        ref_prop.clean("not-my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf")
+
+    assert ref_prop.clean("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf") == \
+        "my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf"
+
+
 @pytest.mark.parametrize(
     "value", [
         '2017-01-01T12:34:56Z',
diff --git a/stix2/test/v21/test_report.py b/stix2/test/v21/test_report.py
index c9d790e..8b7ee78 100644
--- a/stix2/test/v21/test_report.py
+++ b/stix2/test/v21/test_report.py
@@ -88,8 +88,6 @@ def test_report_example_objects_in_object_refs_with_bad_id():
 
     assert excinfo.value.cls == stix2.v21.Report
     assert excinfo.value.prop_name == "object_refs"
-    assert excinfo.value.reason == stix2.properties.ERROR_INVALID_ID
-    assert str(excinfo.value) == "Invalid value for Report 'object_refs': " + stix2.properties.ERROR_INVALID_ID
 
 
 @pytest.mark.parametrize(
diff --git a/stix2/test/v21/test_sighting.py b/stix2/test/v21/test_sighting.py
index 8fcbb6d..cfdc7ea 100644
--- a/stix2/test/v21/test_sighting.py
+++ b/stix2/test/v21/test_sighting.py
@@ -61,8 +61,6 @@ def test_sighting_bad_where_sighted_refs():
 
     assert excinfo.value.cls == stix2.v21.Sighting
     assert excinfo.value.prop_name == "where_sighted_refs"
-    assert excinfo.value.reason == "must start with 'identity'."
-    assert str(excinfo.value) == "Invalid value for Sighting 'where_sighted_refs': must start with 'identity'."
 
 
 def test_sighting_type_must_be_sightings():