Disallow invalid type names in custom classes

stix2.0
Chris Lenk 2018-04-13 14:52:00 -04:00
parent a8b8bfe88b
commit a475fc6dbd
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'
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():
nt_string = """{
"type": "x-new-type",
@ -295,6 +313,24 @@ def test_custom_observable_object_no_init_2():
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():
with pytest.raises(ValueError) as excinfo:
@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)
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():
with pytest.raises(ValueError) as excinfo:
@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_UNMOD_PROPERTIES = ["created", "created_by_ref", "id", "type"]
TYPE_REGEX = r'^\-?[a-z0-9]+(-[a-z0-9]+)*\-?$'
class STIXdatetime(dt.datetime):
def __new__(cls, *args, **kwargs):

View File

@ -6,6 +6,7 @@ Observable and do not have a ``_type`` attribute.
"""
from collections import OrderedDict
import re
from ..base import _Extension, _Observable, _STIXBase
from ..exceptions import (AtLeastOnePropertyError, CustomContentError,
@ -15,7 +16,7 @@ from ..properties import (BinaryProperty, BooleanProperty, DictionaryProperty,
HashesProperty, HexProperty, IntegerProperty,
ListProperty, ObjectReferenceProperty, Property,
StringProperty, TimestampProperty, TypeProperty)
from ..utils import get_dict
from ..utils import TYPE_REGEX, get_dict
class ObservableProperty(Property):
@ -967,6 +968,12 @@ def CustomObservable(type='x-custom-observable', properties=None):
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
_properties = OrderedDict()
_properties.update([
@ -1040,6 +1047,12 @@ def CustomExtension(observable=None, type='x-custom-observable', properties=None
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
_properties = OrderedDict()

View File

@ -2,6 +2,7 @@
"""
from collections import OrderedDict
import re
import stix2
@ -10,7 +11,7 @@ from ..markings import _MarkingsMixin
from ..properties import (BooleanProperty, IDProperty, IntegerProperty,
ListProperty, PatternProperty, ReferenceProperty,
StringProperty, TimestampProperty, TypeProperty)
from ..utils import NOW
from ..utils import NOW, TYPE_REGEX
from .common import ExternalReference, GranularMarking, KillChainPhase
from .observables import ObservableProperty
@ -357,6 +358,13 @@ def CustomObject(type='x-custom-type', properties=None):
def custom_builder(cls):
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
_properties = OrderedDict()
_properties.update([