STIX Extensions

This page is specific for the STIX Extensions mechanism defined in STIX 2.1 CS 02. For the deprecated STIX Customization mechanisms see the Custom section.

Top Level Property Extensions

The example below shows how to create an indicator object with a top-level-property-extension.

[3]:
import stix2

extension_definition1 = stix2.v21.ExtensionDefinition(
    id="extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8",
    created_by_ref="identity--11b76a96-5d2b-45e0-8a5a-f6994f370731",
    created="2014-02-20T09:16:08.000Z",
    modified="2014-02-20T09:16:08.000Z",
    name="New SDO 1",
    description="This schema adds two properties to a STIX object at the toplevel",
    schema="https://www.example.com/schema-foo-1a/v1/",
    version="1.2.1",
    extension_types=["toplevel-property-extension"],
    extension_properties=[
        "toxicity",
        "rank",
    ],
)

indicator = stix2.v21.Indicator(
    id='indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c',
    created='2014-02-20T09:16:08.989000Z',
    modified='2014-02-20T09:16:08.989000Z',
    name='File hash for Poison Ivy variant',
    description='This file hash indicates that a sample of Poison Ivy is present.',
    labels=[
        'malicious-activity',
    ],
    rank=5,
    toxicity=8,
    pattern='[file:hashes.\'SHA-256\' = \'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c\']',
    pattern_type='stix',
    valid_from='2014-02-20T09:00:00.000000Z',
    extensions={
        extension_definition1.id : {
            'extension_type': 'toplevel-property-extension',
        },
    }
)

print(extension_definition1.serialize(pretty=True))
print(indicator.serialize(pretty=True))
[3]:
{
    "type": "extension-definition",
    "spec_version": "2.1",
    "id": "extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8",
    "created_by_ref": "identity--11b76a96-5d2b-45e0-8a5a-f6994f370731",
    "created": "2014-02-20T09:16:08.000Z",
    "modified": "2014-02-20T09:16:08.000Z",
    "name": "New SDO 1",
    "description": "This schema adds two properties to a STIX object at the toplevel",
    "schema": "https://www.example.com/schema-foo-1a/v1/",
    "version": "1.2.1",
    "extension_types": [
        "toplevel-property-extension"
    ],
    "extension_properties": [
        "toxicity",
        "rank"
    ]
}
[3]:
{
    "type": "indicator",
    "spec_version": "2.1",
    "id": "indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c",
    "created": "2014-02-20T09:16:08.989Z",
    "modified": "2014-02-20T09:16:08.989Z",
    "name": "File hash for Poison Ivy variant",
    "description": "This file hash indicates that a sample of Poison Ivy is present.",
    "pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",
    "pattern_type": "stix",
    "pattern_version": "2.1",
    "valid_from": "2014-02-20T09:00:00Z",
    "labels": [
        "malicious-activity"
    ],
    "extensions": {
        "extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8": {
            "extension_type": "toplevel-property-extension"
        }
    },
    "rank": 5,
    "toxicity": 8
}

Using CustomExtension decorator

However, in order to prevent repetitive instantiation of the same extension, the @CustomExtension decorator can be used to register the extension-definition with stix2. Use the extension_type class variable to define what kind of extension it is. Then its id can be passed into objects that use this extension.

[4]:
TOPLEVEL_EXTENSION_DEFINITION_ID = 'extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8'

@stix2.v21.CustomExtension(
    TOPLEVEL_EXTENSION_DEFINITION_ID, [
        ('rank', stix2.properties.IntegerProperty(required=True)),
        ('toxicity', stix2.properties.IntegerProperty(required=True)),
    ],
)
class ExtensionTopLevel:
    extension_type = 'toplevel-property-extension'

indicator = stix2.v21.Indicator(
    id='indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c',
    created='2014-02-20T09:16:08.989000Z',
    modified='2014-02-20T09:16:08.989000Z',
    name='File hash for Poison Ivy variant',
    description='This file hash indicates that a sample of Poison Ivy is present.',
    labels=[
        'malicious-activity',
    ],
    rank=5,
    toxicity=8,
    pattern='[file:hashes.\'SHA-256\' = \'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c\']',
    pattern_type='stix',
    valid_from='2014-02-20T09:00:00.000000Z',
    extensions={
        TOPLEVEL_EXTENSION_DEFINITION_ID : {
            'extension_type': 'toplevel-property-extension',
        },
    }
)

print(indicator.serialize(pretty=True))
[4]:
{
    "type": "indicator",
    "spec_version": "2.1",
    "id": "indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c",
    "created": "2014-02-20T09:16:08.989Z",
    "modified": "2014-02-20T09:16:08.989Z",
    "name": "File hash for Poison Ivy variant",
    "description": "This file hash indicates that a sample of Poison Ivy is present.",
    "pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",
    "pattern_type": "stix",
    "pattern_version": "2.1",
    "valid_from": "2014-02-20T09:00:00Z",
    "labels": [
        "malicious-activity"
    ],
    "extensions": {
        "extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8": {
            "extension_type": "toplevel-property-extension"
        }
    },
    "rank": 5,
    "toxicity": 8
}

Using CustomObservable for Extension Definition

Similarly, when registering new objects via @CustomObservable you can pass the extension-definition id that defines this new SCO.

[3]:
@stix2.v21.CustomObservable(
    'my-favorite-sco', [
        ('name', stix2.properties.StringProperty(required=True)),
        ('some_network_protocol_field', stix2.properties.StringProperty(required=True)),
    ], ['name', 'some_network_protocol_field'], 'extension-definition--150c1738-28c9-44d0-802d-70523218240b',
)
class MyFavSCO:
    pass

my_favorite_sco = MyFavSCO(
    id='my-favorite-sco--f9dbe89c-0030-4a9d-8b78-0dcd0a0de874',
    name='This is the name of my favorite SCO',
    some_network_protocol_field='value',
)

print(my_favorite_sco.serialize(pretty=True))
[3]:
{
    "type": "my-favorite-sco",
    "spec_version": "2.1",
    "id": "my-favorite-sco--f9dbe89c-0030-4a9d-8b78-0dcd0a0de874",
    "name": "This is the name of my favorite SCO",
    "some_network_protocol_field": "value",
    "extensions": {
        "extension-definition--150c1738-28c9-44d0-802d-70523218240b": {
            "extension_type": "new-sco"
        }
    }
}

Using CustomMarking for Extension Definition

The example below shows the use for MarkingDefinition extensions. Currently this is only supported as a property-extension. Now, as another option to building the extensions as a dictionary, it can also be built with objects as shown below by extracting the registered class.

[4]:
from stix2 import registry

MARKING_EXTENSION_ID = 'extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff'

@stix2.v21.CustomMarking(
    'my-favorite-marking', [
        ('some_marking_field', stix2.properties.StringProperty(required=True)),
    ], MARKING_EXTENSION_ID,
)
class MyFavMarking:
    pass

ext_class = registry.class_for_type(MARKING_EXTENSION_ID, '2.1')

my_favorite_marking = MyFavMarking(
    name='This is the name of my favorite Marking',
    extensions={
        MARKING_EXTENSION_ID: ext_class(some_marking_field='value')
    }
)

print(my_favorite_marking.serialize(pretty=True))
[4]:
{
    "type": "marking-definition",
    "spec_version": "2.1",
    "id": "marking-definition--28417f9f-1963-4e7f-914d-233f8fd4829f",
    "created": "2021-03-31T21:54:46.652069Z",
    "name": "This is the name of my favorite Marking",
    "extensions": {
        "extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff": {
            "extension_type": "property-extension"
        }
    }
}

Using CustomObject for Extension Definition

Similar to the examples above, the same can be done for SDOs and SROs.

[4]:
invalid_refs = ['bundle', 'language-content', 'marking-definition', 'relationship', 'sighting', 'foobar']

@stix2.v21.CustomObject(
    'my-favorite-sro', [
        ('name', stix2.properties.StringProperty(required=False)),
        ('some_source_ref', stix2.properties.ReferenceProperty(invalid_types=invalid_refs, spec_version='2.1', required=True)),
        ('some_target_ref', stix2.properties.ReferenceProperty(invalid_types=invalid_refs, spec_version='2.1', required=True)),
    ], extension_name='extension-definition--e96690a5-dc13-4f27-99dd-0f2188ad74ce', is_sdo=False,
)
class MyFavSRO:
    pass


my_favorite_sro = MyFavSRO(
    name="My First SRO",
    some_source_ref="identity--b1da8c3e-34d8-470f-9d2b-392e275f1f7d",
    some_target_ref="identity--1ddfed54-e8cd-49c9-9c7d-8d1b03c94685",
)

print(my_favorite_sro.serialize(pretty=True))
[4]:
{
    "type": "my-favorite-sro",
    "spec_version": "2.1",
    "id": "my-favorite-sro--d6306d62-c08d-4d78-baf7-11e7a4c9bc36",
    "created": "2021-03-31T22:43:42.807698Z",
    "modified": "2021-03-31T22:43:42.807698Z",
    "name": "My First SRO",
    "some_source_ref": "identity--b1da8c3e-34d8-470f-9d2b-392e275f1f7d",
    "some_target_ref": "identity--1ddfed54-e8cd-49c9-9c7d-8d1b03c94685",
    "extensions": {
        "extension-definition--e96690a5-dc13-4f27-99dd-0f2188ad74ce": {
            "extension_type": "new-sro"
        }
    }
}