Merge pull request #167 from oasis-open/invalid-type-names

Disallow invalid type names in custom classes
stix2.0
Chris Lenk 2018-04-13 16:52:36 -04:00 committed by GitHub
commit a1befe6387
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 2 deletions

View File

@ -197,6 +197,24 @@ def test_custom_object_no_init_2():
assert no2.property1 == 'something' assert no2.property1 == 'something'
def test_custom_object_invalid_type_name():
with pytest.raises(ValueError) as excinfo:
@stix2.sdo.CustomObject('x', [
('property1', stix2.properties.StringProperty(required=True)),
])
class NewObj(object):
pass # pragma: no cover
assert "Invalid type name 'x': " in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.sdo.CustomObject('x_new_object', [
('property1', stix2.properties.StringProperty(required=True)),
])
class NewObj2(object):
pass # pragma: no cover
assert "Invalid type name 'x_new_object':" in str(excinfo.value)
def test_parse_custom_object_type(): def test_parse_custom_object_type():
nt_string = """{ nt_string = """{
"type": "x-new-type", "type": "x-new-type",
@ -295,6 +313,24 @@ def test_custom_observable_object_no_init_2():
assert no2.property1 == 'something' assert no2.property1 == 'something'
def test_custom_observable_object_invalid_type_name():
with pytest.raises(ValueError) as excinfo:
@stix2.observables.CustomObservable('x', [
('property1', stix2.properties.StringProperty()),
])
class NewObs(object):
pass # pragma: no cover
assert "Invalid observable type name 'x':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.observables.CustomObservable('x_new_obs', [
('property1', stix2.properties.StringProperty()),
])
class NewObs2(object):
pass # pragma: no cover
assert "Invalid observable type name 'x_new_obs':" in str(excinfo.value)
def test_custom_observable_object_invalid_ref_property(): def test_custom_observable_object_invalid_ref_property():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError) as excinfo:
@stix2.observables.CustomObservable('x-new-obs', [ @stix2.observables.CustomObservable('x-new-obs', [
@ -573,6 +609,24 @@ def test_custom_extension_invalid_observable():
assert "Custom observables must be created with the @CustomObservable decorator." in str(excinfo.value) assert "Custom observables must be created with the @CustomObservable decorator." in str(excinfo.value)
def test_custom_extension_invalid_type_name():
with pytest.raises(ValueError) as excinfo:
@stix2.observables.CustomExtension(stix2.File, 'x', {
'property1': stix2.properties.StringProperty(required=True),
})
class FooExtension():
pass # pragma: no cover
assert "Invalid extension type name 'x':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.observables.CustomExtension(stix2.File, 'x_new_ext', {
'property1': stix2.properties.StringProperty(required=True),
})
class BlaExtension():
pass # pragma: no cover
assert "Invalid extension type name 'x_new_ext':" in str(excinfo.value)
def test_custom_extension_no_properties(): def test_custom_extension_no_properties():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError) as excinfo:
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-ext2', None) @stix2.observables.CustomExtension(stix2.DomainName, 'x-new-ext2', None)

View File

@ -18,6 +18,8 @@ NOW = object()
# STIX object properties that cannot be modified # STIX object properties that cannot be modified
STIX_UNMOD_PROPERTIES = ["created", "created_by_ref", "id", "type"] STIX_UNMOD_PROPERTIES = ["created", "created_by_ref", "id", "type"]
TYPE_REGEX = r'^\-?[a-z0-9]+(-[a-z0-9]+)*\-?$'
class STIXdatetime(dt.datetime): class STIXdatetime(dt.datetime):
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):

View File

@ -7,6 +7,7 @@ Observable and do not have a ``_type`` attribute.
from collections import OrderedDict from collections import OrderedDict
import copy import copy
import re
from ..base import _Extension, _Observable, _STIXBase from ..base import _Extension, _Observable, _STIXBase
from ..exceptions import (AtLeastOnePropertyError, CustomContentError, from ..exceptions import (AtLeastOnePropertyError, CustomContentError,
@ -16,7 +17,7 @@ from ..properties import (BinaryProperty, BooleanProperty, DictionaryProperty,
HashesProperty, HexProperty, IntegerProperty, HashesProperty, HexProperty, IntegerProperty,
ListProperty, ObjectReferenceProperty, Property, ListProperty, ObjectReferenceProperty, Property,
StringProperty, TimestampProperty, TypeProperty) StringProperty, TimestampProperty, TypeProperty)
from ..utils import _get_dict from ..utils import TYPE_REGEX, _get_dict
class ObservableProperty(Property): class ObservableProperty(Property):
@ -981,6 +982,12 @@ def CustomObservable(type='x-custom-observable', properties=None):
class _Custom(cls, _Observable): class _Custom(cls, _Observable):
if not re.match(TYPE_REGEX, type):
raise ValueError("Invalid observable type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
elif len(type) < 3 or len(type) > 250:
raise ValueError("Invalid observable type name '%s': must be between 3 and 250 characters." % type)
_type = type _type = type
_properties = OrderedDict() _properties = OrderedDict()
_properties.update([ _properties.update([
@ -1054,6 +1061,12 @@ def CustomExtension(observable=None, type='x-custom-observable', properties=None
class _Custom(cls, _Extension): class _Custom(cls, _Extension):
if not re.match(TYPE_REGEX, type):
raise ValueError("Invalid extension type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
elif len(type) < 3 or len(type) > 250:
raise ValueError("Invalid extension type name '%s': must be between 3 and 250 characters." % type)
_type = type _type = type
_properties = OrderedDict() _properties = OrderedDict()

View File

@ -2,6 +2,7 @@
""" """
from collections import OrderedDict from collections import OrderedDict
import re
import stix2 import stix2
@ -10,7 +11,7 @@ from ..markings import _MarkingsMixin
from ..properties import (BooleanProperty, IDProperty, IntegerProperty, from ..properties import (BooleanProperty, IDProperty, IntegerProperty,
ListProperty, PatternProperty, ReferenceProperty, ListProperty, PatternProperty, ReferenceProperty,
StringProperty, TimestampProperty, TypeProperty) StringProperty, TimestampProperty, TypeProperty)
from ..utils import NOW from ..utils import NOW, TYPE_REGEX
from .common import ExternalReference, GranularMarking, KillChainPhase from .common import ExternalReference, GranularMarking, KillChainPhase
from .observables import ObservableProperty from .observables import ObservableProperty
@ -357,6 +358,13 @@ def CustomObject(type='x-custom-type', properties=None):
def custom_builder(cls): def custom_builder(cls):
class _Custom(cls, STIXDomainObject): class _Custom(cls, STIXDomainObject):
if not re.match(TYPE_REGEX, type):
raise ValueError("Invalid type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
elif len(type) < 3 or len(type) > 250:
raise ValueError("Invalid type name '%s': must be between 3 and 250 characters." % type)
_type = type _type = type
_properties = OrderedDict() _properties = OrderedDict()
_properties.update([ _properties.update([