diff --git a/stix2/base.py b/stix2/base.py index b2e20de..dba5d71 100644 --- a/stix2/base.py +++ b/stix2/base.py @@ -143,7 +143,7 @@ class _STIXBase(collections.Mapping): def __init__(self, allow_custom=False, **kwargs): cls = self.__class__ - self.__allow_custom = allow_custom + self._allow_custom = allow_custom # Use the same timestamp for any auto-generated datetimes self.__now = get_timestamp() @@ -152,12 +152,12 @@ class _STIXBase(collections.Mapping): custom_props = kwargs.pop('custom_properties', {}) if custom_props and not isinstance(custom_props, dict): raise ValueError("'custom_properties' must be a dictionary") - if not self.__allow_custom: + if not self._allow_custom: extra_kwargs = list(set(kwargs) - set(self._properties)) if extra_kwargs: raise ExtraPropertiesError(cls, extra_kwargs) if custom_props: - self.__allow_custom = True + self._allow_custom = True # Remove any keyword arguments whose value is None or [] (i.e. empty list) setting_kwargs = {} @@ -235,7 +235,7 @@ class _STIXBase(collections.Mapping): if isinstance(self, _Observable): # Assume: valid references in the original object are still valid in the new version new_inner['_valid_refs'] = {'*': '*'} - new_inner['allow_custom'] = self.__allow_custom + new_inner['allow_custom'] = self._allow_custom return cls(**new_inner) def properties_populated(self): @@ -306,7 +306,7 @@ class _Observable(_STIXBase): # the constructor might be called independently of an observed data object self._STIXBase__valid_refs = kwargs.pop('_valid_refs', []) - self.__allow_custom = kwargs.get('allow_custom', False) + self._allow_custom = kwargs.get('allow_custom', False) self._properties['extensions'].allow_custom = kwargs.get('allow_custom', False) try: diff --git a/stix2/properties.py b/stix2/properties.py index 8eb7303..b1199b8 100644 --- a/stix2/properties.py +++ b/stix2/properties.py @@ -16,8 +16,8 @@ import stix2 from .base import _Observable, _STIXBase from .core import STIX2_OBJ_MAPS, parse, parse_observable from .exceptions import ( - CustomContentError, DictionaryKeyError, ExtraPropertiesError, - MissingPropertiesError, MutuallyExclusivePropertiesError, + CustomContentError, DictionaryKeyError, MissingPropertiesError, + MutuallyExclusivePropertiesError, ) from .utils import _get_dict, get_class_hierarchy_names, parse_into_datetime @@ -201,8 +201,10 @@ class ListProperty(Property): if isinstance(valid, collections.Mapping): try: + valid._allow_custom + except AttributeError: result.append(obj_type(**valid)) - except ExtraPropertiesError: + else: result.append(obj_type(allow_custom=True, **valid)) else: result.append(obj_type(valid)) diff --git a/stix2/test/v21/test_indicator.py b/stix2/test/v21/test_indicator.py index bc4cd82..d441ba5 100644 --- a/stix2/test/v21/test_indicator.py +++ b/stix2/test/v21/test_indicator.py @@ -233,3 +233,19 @@ def test_indicator_with_custom_embedded_objs(): assert ind.indicator_types == ['malicious-activity'] assert len(ind.external_references) == 1 assert ind.external_references[0] == ext_ref + + +def test_indicator_with_custom_embed_objs_extra_props_error(): + ext_ref = stix2.v21.ExternalReference( + source_name="Test", + description="Example Custom Ext Ref", + random_custom_prop="This is a custom property", + allow_custom=True, + ) + + with pytest.raises(stix2.exceptions.ExtraPropertiesError) as excinfo: + stix2.v21.Indicator(external_references=[ext_ref], bad_custom_prop="shouldn't be here", **INDICATOR_KWARGS) + + assert excinfo.value.cls == stix2.v21.Indicator + assert excinfo.value.properties == ['bad_custom_prop'] + assert str(excinfo.value) == "Unexpected properties for Indicator: (bad_custom_prop)." diff --git a/stix2/v20/bundle.py b/stix2/v20/bundle.py index 1383757..ffd70ea 100644 --- a/stix2/v20/bundle.py +++ b/stix2/v20/bundle.py @@ -31,7 +31,7 @@ class Bundle(_STIXBase): else: kwargs['objects'] = list(args) + kwargs.get('objects', []) - self.__allow_custom = kwargs.get('allow_custom', False) + self._allow_custom = kwargs.get('allow_custom', False) self._properties['objects'].contained.allow_custom = kwargs.get('allow_custom', False) super(Bundle, self).__init__(**kwargs) diff --git a/stix2/v20/sdo.py b/stix2/v20/sdo.py index 19c53d8..19d5437 100644 --- a/stix2/v20/sdo.py +++ b/stix2/v20/sdo.py @@ -212,7 +212,7 @@ class ObservedData(STIXDomainObject): ]) def __init__(self, *args, **kwargs): - self.__allow_custom = kwargs.get('allow_custom', False) + self._allow_custom = kwargs.get('allow_custom', False) self._properties['objects'].allow_custom = kwargs.get('allow_custom', False) super(ObservedData, self).__init__(*args, **kwargs) diff --git a/stix2/v21/bundle.py b/stix2/v21/bundle.py index fb35be2..168771f 100644 --- a/stix2/v21/bundle.py +++ b/stix2/v21/bundle.py @@ -29,7 +29,7 @@ class Bundle(_STIXBase): else: kwargs['objects'] = list(args) + kwargs.get('objects', []) - self.__allow_custom = kwargs.get('allow_custom', False) + self._allow_custom = kwargs.get('allow_custom', False) self._properties['objects'].contained.allow_custom = kwargs.get('allow_custom', False) super(Bundle, self).__init__(**kwargs) diff --git a/stix2/v21/sdo.py b/stix2/v21/sdo.py index 7cd7891..9317825 100644 --- a/stix2/v21/sdo.py +++ b/stix2/v21/sdo.py @@ -571,7 +571,7 @@ class ObservedData(STIXDomainObject): ]) def __init__(self, *args, **kwargs): - self.__allow_custom = kwargs.get('allow_custom', False) + self._allow_custom = kwargs.get('allow_custom', False) self._properties['objects'].allow_custom = kwargs.get('allow_custom', False) if "objects" in kwargs: