Disallow missing 'type' property with allow_custom
There was a bug where if you allowed custom content the library would parse an object without the required 'type' property.stix2.0
							parent
							
								
									91376586d4
								
							
						
					
					
						commit
						fc6a33b23e
					
				|  | @ -6,11 +6,11 @@ import datetime as dt | |||
| 
 | ||||
| import simplejson as json | ||||
| 
 | ||||
| from .exceptions import (AtLeastOnePropertyError, DependentPropertiesError, | ||||
|                          ExtraPropertiesError, ImmutableError, | ||||
|                          InvalidObjRefError, InvalidValueError, | ||||
| from .exceptions import (AtLeastOnePropertyError, CustomContentError, | ||||
|                          DependentPropertiesError, ExtraPropertiesError, | ||||
|                          ImmutableError, InvalidObjRefError, InvalidValueError, | ||||
|                          MissingPropertiesError, | ||||
|                          MutuallyExclusivePropertiesError, ParseError) | ||||
|                          MutuallyExclusivePropertiesError) | ||||
| from .markings.utils import validate | ||||
| from .utils import NOW, find_property_index, format_datetime, get_timestamp | ||||
| from .utils import new_version as _new_version | ||||
|  | @ -61,7 +61,7 @@ class _STIXBase(collections.Mapping): | |||
|             try: | ||||
|                 kwargs[prop_name] = prop.clean(kwargs[prop_name]) | ||||
|             except ValueError as exc: | ||||
|                 if self.__allow_custom and isinstance(exc, ParseError): | ||||
|                 if self.__allow_custom and isinstance(exc, CustomContentError): | ||||
|                     return | ||||
|                 raise InvalidValueError(self.__class__, prop_name, reason=str(exc)) | ||||
| 
 | ||||
|  |  | |||
|  | @ -163,6 +163,13 @@ class ParseError(STIXError, ValueError): | |||
|         super(ParseError, self).__init__(msg) | ||||
| 
 | ||||
| 
 | ||||
| class CustomContentError(STIXError, ValueError): | ||||
|     """Custom STIX Content (SDO, Observable, Extension, etc.) detected.""" | ||||
| 
 | ||||
|     def __init__(self, msg): | ||||
|         super(CustomContentError, self).__init__(msg) | ||||
| 
 | ||||
| 
 | ||||
| class InvalidSelectorError(STIXError, AssertionError): | ||||
|     """Granular Marking selector violation. The selector must resolve into an existing STIX object property.""" | ||||
| 
 | ||||
|  |  | |||
|  | @ -373,7 +373,7 @@ def test_parse_unregistered_custom_observable_object(): | |||
|         "property1": "something" | ||||
|     }""" | ||||
| 
 | ||||
|     with pytest.raises(stix2.exceptions.ParseError) as excinfo: | ||||
|     with pytest.raises(stix2.exceptions.CustomContentError) as excinfo: | ||||
|         stix2.parse_observable(nt_string) | ||||
|     assert "Can't parse unknown observable type" in str(excinfo.value) | ||||
| 
 | ||||
|  | @ -384,6 +384,16 @@ def test_parse_unregistered_custom_observable_object(): | |||
|     assert not isinstance(parsed_custom, stix2.core._STIXBase) | ||||
| 
 | ||||
| 
 | ||||
| def test_parse_unregistered_custom_observable_object_with_no_type(): | ||||
|     nt_string = """{ | ||||
|         "property1": "something" | ||||
|     }""" | ||||
| 
 | ||||
|     with pytest.raises(stix2.exceptions.ParseError) as excinfo: | ||||
|         stix2.parse_observable(nt_string, allow_custom=True) | ||||
|     assert "Can't parse observable with no 'type' property" in str(excinfo.value) | ||||
| 
 | ||||
| 
 | ||||
| def test_parse_observed_data_with_custom_observable(): | ||||
|     input_str = """{ | ||||
|         "type": "observed-data", | ||||
|  |  | |||
|  | @ -8,8 +8,8 @@ Observable and do not have a ``_type`` attribute. | |||
| from collections import OrderedDict | ||||
| 
 | ||||
| from ..base import _Extension, _Observable, _STIXBase | ||||
| from ..exceptions import (AtLeastOnePropertyError, DependentPropertiesError, | ||||
|                           ParseError) | ||||
| from ..exceptions import (AtLeastOnePropertyError, CustomContentError, | ||||
|                           DependentPropertiesError, ParseError) | ||||
| from ..properties import (BinaryProperty, BooleanProperty, DictionaryProperty, | ||||
|                           EmbeddedObjectProperty, EnumProperty, FloatProperty, | ||||
|                           HashesProperty, HexProperty, IntegerProperty, | ||||
|  | @ -67,7 +67,7 @@ class ExtensionsProperty(DictionaryProperty): | |||
|                     else: | ||||
|                         raise ValueError("Cannot determine extension type.") | ||||
|                 else: | ||||
|                     raise ParseError("Can't parse unknown extension type: {}".format(key)) | ||||
|                     raise CustomContentError("Can't parse unknown extension type: {}".format(key)) | ||||
|         else: | ||||
|             raise ValueError("The enclosing type '%s' has no extensions defined" % self.enclosing_type) | ||||
|         return dictified | ||||
|  | @ -927,8 +927,8 @@ def parse_observable(data, _valid_refs=None, allow_custom=False): | |||
|             # flag allows for unknown custom objects too, but will not | ||||
|             # be parsed into STIX observable object, just returned as is | ||||
|             return obj | ||||
|         raise ParseError("Can't parse unknown observable type '%s'! For custom observables, " | ||||
|                          "use the CustomObservable decorator." % obj['type']) | ||||
|         raise CustomContentError("Can't parse unknown observable type '%s'! For custom observables, " | ||||
|                                  "use the CustomObservable decorator." % obj['type']) | ||||
| 
 | ||||
|     if 'extensions' in obj and obj['type'] in EXT_MAP: | ||||
|         for name, ext in obj['extensions'].items(): | ||||
|  | @ -936,7 +936,8 @@ def parse_observable(data, _valid_refs=None, allow_custom=False): | |||
|                 ext_class = EXT_MAP[obj['type']][name] | ||||
|             except KeyError: | ||||
|                 if not allow_custom: | ||||
|                     raise ParseError("Can't parse unknown extension type '%s' for observable type '%s'!" % (name, obj['type'])) | ||||
|                     raise CustomContentError("Can't parse unknown extension type '%s'" | ||||
|                                              "for observable type '%s'!" % (name, obj['type'])) | ||||
|             else:  # extension was found | ||||
|                 obj['extensions'][name] = ext_class(allow_custom=allow_custom, **obj['extensions'][name]) | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Chris Lenk
						Chris Lenk