From f5ae9798f8bb40c71ce4737f3b97940a7cd388ef Mon Sep 17 00:00:00 2001 From: Rich Piazza Date: Thu, 14 Mar 2024 16:46:07 -0400 Subject: [PATCH 01/13] update python versions to 3.8-3.12 --- setup.py | 5 +++-- tox.ini | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 499af4f1..80edabb4 100644 --- a/setup.py +++ b/setup.py @@ -38,14 +38,15 @@ def get_long_description(): 'Topic :: Security', 'License :: OSI Approved :: BSD License', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', ], keywords='stix stix2 json cti cyber threat intelligence', packages=find_packages(exclude=['*.test', '*.test.*']), - python_requires='>=3.7', + python_requires='>=3.8', install_requires=[ 'pytz', 'requests', diff --git a/tox.ini b/tox.ini index 26974585..bc7bd5b6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,8 @@ [tox] -envlist = py37,py38,py39,py310,packaging,pre-commit-check +envlist = py38,py39,py310,py311,py312,packaging,pre-commit-check [testenv] deps = - -U tox pytest pytest-cov @@ -32,7 +31,8 @@ commands = [gh-actions] python = - 3.7: py37 3.8: py38 - 3.9: py39, packaging, pre-commit-check + 3.9: py39 3.10: py310 + 3.11: py311, packaging, pre-commit-check + 3.12: py312 From 9f70e6860e797ff0097a0aa40f49b1b4f8fa50cc Mon Sep 17 00:00:00 2001 From: Rich Piazza Date: Thu, 14 Mar 2024 16:53:31 -0400 Subject: [PATCH 02/13] fix workflows python versions --- .github/workflows/python-ci-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-ci-tests.yml b/.github/workflows/python-ci-tests.yml index 211aa4c5..6ca27d5f 100644 --- a/.github/workflows/python-ci-tests.yml +++ b/.github/workflows/python-ci-tests.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9, '3.10'] + python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] name: Python ${{ matrix.python-version }} Build steps: From 4f0e1d205abe43933bb17ee4f04047da88086c8a Mon Sep 17 00:00:00 2001 From: Rich Piazza Date: Sat, 16 Mar 2024 13:53:34 -0400 Subject: [PATCH 03/13] fiux test-environments - weights changed --- stix2/test/v20/test_environment.py | 12 ++++++------ stix2/test/v21/test_environment.py | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/stix2/test/v20/test_environment.py b/stix2/test/v20/test_environment.py index c8867b01..b6f3a0b3 100644 --- a/stix2/test/v20/test_environment.py +++ b/stix2/test/v20/test_environment.py @@ -515,12 +515,12 @@ def test_graph_similarity_with_filesystem_source(ds, fs): prop_scores2 = {} env2 = stix2.Environment().graph_similarity(ds, fs, prop_scores2, ignore_spec_version=True) - assert round(env1) == 25 - assert round(prop_scores1["matching_score"]) == 451 + assert round(env1) == 19 + assert round(prop_scores1["matching_score"]) == 334 assert round(prop_scores1["len_pairs"]) == 18 - assert round(env2) == 25 - assert round(prop_scores2["matching_score"]) == 451 + assert round(env2) == 19 + assert round(prop_scores2["matching_score"]) == 334 assert round(prop_scores2["len_pairs"]) == 18 prop_scores1["matching_score"] = round(prop_scores1["matching_score"], 3) @@ -587,11 +587,11 @@ def test_graph_equivalence_with_filesystem_source(ds, fs): env2 = stix2.Environment().graph_equivalence(ds, fs, prop_scores2, ignore_spec_version=True) assert env1 is False - assert round(prop_scores1["matching_score"]) == 451 + assert round(prop_scores1["matching_score"]) == 334 assert round(prop_scores1["len_pairs"]) == 18 assert env2 is False - assert round(prop_scores2["matching_score"]) == 451 + assert round(prop_scores2["matching_score"]) == 334 assert round(prop_scores2["len_pairs"]) == 18 prop_scores1["matching_score"] = round(prop_scores1["matching_score"], 3) diff --git a/stix2/test/v21/test_environment.py b/stix2/test/v21/test_environment.py index 883ff012..51ca15a5 100644 --- a/stix2/test/v21/test_environment.py +++ b/stix2/test/v21/test_environment.py @@ -900,7 +900,7 @@ def test_object_similarity_prop_scores(): tool2 = stix2.v21.Tool(id=TOOL_ID, **TOOL2_KWARGS) stix2.Environment().object_similarity(tool1, tool2, prop_scores) assert len(prop_scores) == 4 - assert round(prop_scores["matching_score"], 1) == 8.9 + assert round(prop_scores["matching_score"], 1) == 0.0 assert round(prop_scores["sum_weights"], 1) == 100.0 @@ -1050,12 +1050,12 @@ def test_graph_similarity_with_filesystem_source(ds, fs): max_depth=1, ) - assert round(env1) == 23 - assert round(prop_scores1["matching_score"]) == 411 + assert round(env1) == 17 + assert round(prop_scores1["matching_score"]) == 308 assert round(prop_scores1["len_pairs"]) == 18 - assert round(env2) == 23 - assert round(prop_scores2["matching_score"]) == 411 + assert round(env2) == 17 + assert round(prop_scores2["matching_score"]) == 308 assert round(prop_scores2["len_pairs"]) == 18 prop_scores1["matching_score"] = round(prop_scores1["matching_score"], 3) @@ -1225,11 +1225,11 @@ def test_graph_equivalence_with_filesystem_source(ds, fs): env2 = stix2.Environment().graph_equivalence(ds, fs, prop_scores2, ignore_spec_version=True) assert env1 is False - assert round(prop_scores1["matching_score"]) == 411 + assert round(prop_scores1["matching_score"]) == 308 assert round(prop_scores1["len_pairs"]) == 18 assert env2 is False - assert round(prop_scores2["matching_score"]) == 411 + assert round(prop_scores2["matching_score"]) == 308 assert round(prop_scores2["len_pairs"]) == 18 prop_scores1["matching_score"] = round(prop_scores1["matching_score"], 3) From 4a3f99f251d4a6c75c270fd1890c5e944cf8d33b Mon Sep 17 00:00:00 2001 From: Rich Piazza Date: Mon, 18 Mar 2024 09:57:59 -0400 Subject: [PATCH 04/13] update isort to 5.12 --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 434eb957..c39aaf6d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: args: - --max-line-length=160 - repo: https://github.com/PyCQA/isort - rev: 5.7.0 + rev: 5.12.0 hooks: - id: isort name: Sort python imports (shows diff) From 647987dfa6711a929d035bc5acd4bd5d7706c59c Mon Sep 17 00:00:00 2001 From: Chris Lenk Date: Mon, 15 Apr 2024 17:11:28 -0400 Subject: [PATCH 05/13] Prevent codecov workflow errors --- .github/workflows/python-ci-tests.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-ci-tests.yml b/.github/workflows/python-ci-tests.yml index 6ca27d5f..47f860e1 100644 --- a/.github/workflows/python-ci-tests.yml +++ b/.github/workflows/python-ci-tests.yml @@ -27,7 +27,8 @@ jobs: run: | tox - name: Upload coverage information to Codecov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v4.2.0 with: - fail_ci_if_error: true # optional (default = false) + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false # optional (default = false) verbose: true # optional (default = false) From 280d34531cfa32436724f5e3aff702b9559f22e8 Mon Sep 17 00:00:00 2001 From: Pedro Henrique Fernandes Date: Thu, 11 Jul 2024 10:58:10 -0300 Subject: [PATCH 06/13] feat: add 'pretty' parameter to optimize JSON serialization performance --- stix2/datastore/filesystem.py | 17 +++++----- stix2/test/v21/test_datastore_filesystem.py | 36 +++++++++++++++++++++ 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/stix2/datastore/filesystem.py b/stix2/datastore/filesystem.py index 2209116a..d6f83273 100644 --- a/stix2/datastore/filesystem.py +++ b/stix2/datastore/filesystem.py @@ -554,7 +554,7 @@ def __init__(self, stix_dir, allow_custom=False, bundlify=False): def stix_dir(self): return self._stix_dir - def _check_path_and_write(self, stix_obj, encoding='utf-8'): + def _check_path_and_write(self, stix_obj, encoding='utf-8', pretty=True): """Write the given STIX object to a file in the STIX file directory. """ type_dir = os.path.join(self._stix_dir, stix_obj["type"]) @@ -585,9 +585,9 @@ def _check_path_and_write(self, stix_obj, encoding='utf-8'): raise DataSourceError("Attempted to overwrite file (!) at: {}".format(file_path)) with io.open(file_path, mode='w', encoding=encoding) as f: - fp_serialize(stix_obj, f, pretty=True, encoding=encoding, ensure_ascii=False) + fp_serialize(stix_obj, f, pretty=pretty, encoding=encoding, ensure_ascii=False) - def add(self, stix_data=None, version=None): + def add(self, stix_data=None, version=None, pretty=True): """Add STIX objects to file directory. Args: @@ -597,6 +597,7 @@ def add(self, stix_data=None, version=None): version (str): If present, it forces the parser to use the version provided. Otherwise, the library will make the best effort based on checking the "spec_version" property. + pretty (bool): If True, the resulting JSON will be "pretty printed" Note: ``stix_data`` can be a Bundle object, but each object in it will be @@ -607,24 +608,24 @@ def add(self, stix_data=None, version=None): if isinstance(stix_data, (v20.Bundle, v21.Bundle)): # recursively add individual STIX objects for stix_obj in stix_data.get("objects", []): - self.add(stix_obj, version=version) + self.add(stix_obj, version=version, pretty=pretty) elif isinstance(stix_data, _STIXBase): # adding python STIX object - self._check_path_and_write(stix_data) + self._check_path_and_write(stix_data, pretty=pretty) elif isinstance(stix_data, (str, dict)): parsed_data = parse(stix_data, allow_custom=self.allow_custom, version=version) if isinstance(parsed_data, _STIXBase): - self.add(parsed_data, version=version) + self.add(parsed_data, version=version, pretty=pretty) else: # custom unregistered object type - self._check_path_and_write(parsed_data) + self._check_path_and_write(parsed_data, pretty=pretty) elif isinstance(stix_data, list): # recursively add individual STIX objects for stix_obj in stix_data: - self.add(stix_obj) + self.add(stix_obj, version=version, pretty=pretty) else: raise TypeError( diff --git a/stix2/test/v21/test_datastore_filesystem.py b/stix2/test/v21/test_datastore_filesystem.py index 3eb20b5f..39b45578 100644 --- a/stix2/test/v21/test_datastore_filesystem.py +++ b/stix2/test/v21/test_datastore_filesystem.py @@ -151,6 +151,42 @@ def test_filesystem_source_bad_stix_file(fs_source, bad_stix_files): except STIXError as e: assert "Can't parse object with no 'type' property" in str(e) +def test_filesystem_sink_add_pretty_true(fs_sink, fs_source): + """Test adding a STIX object with pretty=True.""" + camp1 = stix2.v21.Campaign( + name="Hannibal", + objective="Targeting Italian and Spanish Diplomat internet accounts", + aliases=["War Elephant"], + ) + fs_sink.add(camp1, pretty=True) + filepath = os.path.join( + FS_PATH, "campaign", camp1.id, _timestamp2filename(camp1.modified) + ".json", + ) + assert os.path.exists(filepath) + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + assert '\n' in content # Check for pretty-printed output + + os.remove(filepath) + +def test_filesystem_sink_add_pretty_false(fs_sink, fs_source): + """Test adding a STIX object with pretty=False.""" + camp1 = stix2.v21.Campaign( + name="Hannibal", + objective="Targeting Italian and Spanish Diplomat internet accounts", + aliases=["War Elephant"], + ) + fs_sink.add(camp1, pretty=False) + filepath = os.path.join( + FS_PATH, "campaign", camp1.id, _timestamp2filename(camp1.modified) + ".json", + ) + assert os.path.exists(filepath) + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + assert '\n' not in content # Check for non-pretty-printed output + + os.remove(filepath) + def test_filesystem_source_get_object(fs_source): # get (latest) object From 33455bd3bc18efd5e99133af2e07faa94c4657cd Mon Sep 17 00:00:00 2001 From: Rich Piazza Date: Mon, 19 Aug 2024 15:45:28 -0400 Subject: [PATCH 07/13] deterministic-id-checker --- determinsitic-id-checker.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 determinsitic-id-checker.py diff --git a/determinsitic-id-checker.py b/determinsitic-id-checker.py new file mode 100644 index 00000000..9f45a020 --- /dev/null +++ b/determinsitic-id-checker.py @@ -0,0 +1,15 @@ +import json +import stix2 + +def main(): + with open("sco-examples-bundle.json", "r", encoding="utf-8") as examples: + all_examples = json.load(examples) + for obj in all_examples: + existing_id = obj["id"] + del obj["id"] + stix_obj = stix2.parse(obj) + print(f"id {existing_id} should be {stix_obj['id']}") + + +if __name__ == "__main__": + main() \ No newline at end of file From 249b2db6d3f02971cd2c276790f1b8fb7324837f Mon Sep 17 00:00:00 2001 From: Rich Piazza Date: Tue, 20 Aug 2024 09:30:59 -0400 Subject: [PATCH 08/13] flaky --- determinsitic-id-checker.py | 2 + sco-examples-bundle.json | 917 ++++++++++++++++++++++++++++++++++++ 2 files changed, 919 insertions(+) create mode 100644 sco-examples-bundle.json diff --git a/determinsitic-id-checker.py b/determinsitic-id-checker.py index 9f45a020..67a9d8a2 100644 --- a/determinsitic-id-checker.py +++ b/determinsitic-id-checker.py @@ -1,6 +1,8 @@ import json + import stix2 + def main(): with open("sco-examples-bundle.json", "r", encoding="utf-8") as examples: all_examples = json.load(examples) diff --git a/sco-examples-bundle.json b/sco-examples-bundle.json new file mode 100644 index 00000000..eca6f64a --- /dev/null +++ b/sco-examples-bundle.json @@ -0,0 +1,917 @@ +[ + { + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--b4e29b62-2053-47c4-bab4-bbce39e5ed67", + "value": "198.51.100.3" + }, + { + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--84445275-e371-444b-baea-ac7d07a180fd", + "value": "198.52.200.4" + }, + { + "type": "file", + "id": "file--1190f2c9-166f-55f1-9706-eea3971d8082", + "spec_version": "2.1", + "hashes": { + "MD5": "a92e5b2bae0b4b3a3d81c85610b95cd4", + "SHA-1": "5374e08903744ceeaedd8f5e1bfc06b2c4688e76" + }, + "size": 77312, + "name": "a92e5b2bae.exe", + "parent_directory_ref": "directory--255cb0e4-8bdb-5d63-bb32-9c6f0b733ab2" + }, + { + "type": "directory", + "id": "directory--255cb0e4-8bdb-5d63-bb32-9c6f0b733ab2", + "spec_version": "2.1", + "path": "C:\\" + }, + { + "type": "domain-name", + "spec_version": "2.1", + "id": "domain-name--ecb120bf-2694-4902-a737-62b74539a41b", + "value": "example.com", + "resolves_to_refs": [ + "ipv4-addr--efcd5e80-570d-4131-b213-62cb18eaa6a8" + ] + }, + { + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--efcd5e80-570d-4131-b213-62cb18eaa6a8", + "value": "198.51.100.3" + }, + { + "type": "artifact", + "spec_version": "2.1", + "id": "artifact--ca17bcf8-9846-5ab4-8662-75c1bf6e63ee", + "mime_type": "image/jpeg", + "payload_bin": "VBORw0KGgoAAAANSUhEUgAAADI== ..." + }, + { + "type": "artifact", + "spec_version": "2.1", + "id": "artifact--6f437177-6e48-5cf8-9d9e-872a2bddd641", + "mime_type": "application/zip", + "payload_bin": "ZX7HIBWPQA99NSUhEUgAAADI== ...", + "encryption_algorithm": "mime-type-indicated", + "decryption_key": "My voice is my passport" + }, + { + "type": "autonomous-system", + "spec_version": "2.1", + "id": "autonomous-system--f720c34b-98ae-597f-ade5-27dc241e8c74", + "number": 15139, + "name": "Slime Industries", + "rir": "ARIN" + }, + { + "type": "directory", + "spec_version": "2.1", + "id": "directory--93c0a9b0-520d-545d-9094-1a08ddf46b05", + "path": "C:\\Windows\\System32" + }, + { + "type": "domain-name", + "spec_version": "2.1", + "id": "domain-name--3c10e93f-798e-5a26-a0c1-08156efab7f5", + "value": "example.com", + "resolves_to_refs": [ + "ipv4-addr--ff26c055-6336-5bc5-b98d-13d6226742dd" + ] + }, + { + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--ff26c055-6336-5bc5-b98d-13d6226742dd", + "value": "198.51.100.3" + }, + { + "type": "email-addr", + "spec_version": "2.1", + "id": "email-addr--2d77a846-6264-5d51-b586-e43822ea1ea3", + "value": "john@example.com", + "display_name": "John Doe" + }, + { + "type": "email-message", + "spec_version": "2.1", + "id": "email-message--72b7698f-10c2-565a-a2a6-b4996a2f2265", + "from_ref": "email-addr--89f52ea8-d6ef-51e9-8fce-6a29236436ed", + "to_refs": [ + "email-addr--e4ee5301-b52d-59cd-a8fa-8036738c7194" + ], + "is_multipart": false, + "date": "1997-11-21T15:55:06.000Z", + "subject": "Saying Hello" + }, + { + "type": "email-addr", + "spec_version": "2.1", + "id": "email-addr--89f52ea8-d6ef-51e9-8fce-6a29236436ed", + "value": "jdoe@example.com", + "display_name": "John Doe" + }, + { + "type": "email-addr", + "spec_version": "2.1", + "id": "email-addr--e4ee5301-b52d-59cd-a8fa-8036738c7194", + "value": "mary@example.com", + "display_name": "Mary Smith" + }, + { + "type": "email-message", + "spec_version": "2.1", + "id": "email-message--cf9b4b7f-14c8-5955-8065-020e0316b559", + "is_multipart": true, + "received_lines": [ + "from mail.example.com ([198.51.100.3]) by smtp.gmail.com with ESMTPSA id q23sm23309939wme.17.2016.07.19.07.20.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 19 Jul 2016 07:20:40 -0700 (PDT)" + ], + "content_type": "multipart/mixed", + "date": "2016-06-19T14:20:40.000Z", + "from_ref": "email-addr--89f52ea8-d6ef-51e9-8fce-6a29236436ed", + "to_refs": [ + "email-addr--d1b3bf0c-f02a-51a1-8102-11aba7959868" + ], + "cc_refs": [ + "email-addr--e4ee5301-b52d-59cd-a8fa-8036738c7194" + ], + "subject": "Check out this picture of a cat!", + "additional_header_fields": { + "Content-Disposition": "inline", + "X-Mailer": "Mutt/1.5.23", + "X-Originating-IP": "198.51.100.3" + }, + "body_multipart": [ + { + "content_type": "text/plain; charset=utf-8", + "content_disposition": "inline", + "body": "Cats are funny!" + }, + { + "content_type": "image/png", + "content_disposition": "attachment; filename=\"tabby.png\"", + "body_raw_ref": "artifact--4cce66f8-6eaa-53cb-85d5-3a85fca3a6c5" + }, + { + "content_type": "application/zip", + "content_disposition": "attachment; filename=\"tabby_pics.zip\"", + "body_raw_ref": "file--6ce09d9c-0ad3-5ebf-900c-e3cb288955b5" + } + ] + }, + { + "type": "email-addr", + "spec_version": "2.1", + "id": "email-addr--89f52ea8-d6ef-51e9-8fce-6a29236436ed", + "value": "jdoe@example.com", + "display_name": "John Doe" + }, + { + "type": "email-addr", + "spec_version": "2.1", + "id": "email-addr--d1b3bf0c-f02a-51a1-8102-11aba7959868", + "value": "bob@example.com", + "display_name": "Bob Smith" + }, + { + "type": "email-addr", + "spec_version": "2.1", + "id": "email-addr--e4ee5301-b52d-59cd-a8fa-8036738c7194", + "value": "mary@example.com", + "display_name": "Mary Smith" + }, + { + "type": "artifact", + "spec_version": "2.1", + "id": "artifact--4cce66f8-6eaa-53cb-85d5-3a85fca3a6c5", + "mime_type": "image/jpeg", + "payload_bin": "VBORw0KGgoAAAANSUhEUgAAADI== ...", + "hashes": { + "SHA-256": "effb46bba03f6c8aea5c653f9cf984f170dcdd3bbbe2ff6843c3e5da0e698766" + } + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--6ce09d9c-0ad3-5ebf-900c-e3cb288955b5", + "name": "tabby_pics.zip", + "magic_number_hex": "504B0304", + "hashes": { + "SHA-256": "fe90a7e910cb3a4739bed9180e807e93fa70c90f25a8915476f5e4bfbac681db" + } + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--e277603e-1060-5ad4-9937-c26c97f1ca68", + "hashes": { + "SHA-256": "fe90a7e910cb3a4739bed9180e807e93fa70c90f25a8915476f5e4bfbac681db" + }, + "size": 25536, + "name": "foo.dll" + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--90bd400b-89a5-51a5-b17d-55bc7719723b", + "hashes": { + "SHA-256": "841a8921140aba50671ebb0770fecc4ee308c4952cfeff8de154ab14eeef4649" + }, + "name": "quĂȘry.dll", + "name_enc": "windows-1252" + }, + { + "type": "directory", + "spec_version": "2.1", + "id": "directory--93c0a9b0-520d-545d-9094-1a08ddf46b05", + "path": "C:\\Windows\\System32" + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--5a27d487-c542-5f97-a131-a8866b477b46", + "hashes": { + "SHA-256": "ceafbfd424be2ca4a5f0402cae090dda2fb0526cf521b60b60077c0f622b285a" + }, + "parent_directory_ref": "directory--93c0a9b0-520d-545d-9094-1a08ddf46b05", + "name": "qwerty.dll" + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--019fde1c-94ca-5967-8b3c-a906a51d87ac", + "hashes": { + "SHA-256": "ceafbfd424be2ca4a5f0402cae090dda2fb0526cf521b60b60077c0f622b285a" + } + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--94fc2163-dec3-5715-b824-6e689c4de865", + "hashes": { + "SHA-256": "19c549ec2628b989382f6b280cbd7bb836a0b461332c0fe53511ce7d584b89d3" + } + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--d07ff290-d7e0-545b-a2ff-04602a9e0b73", + "hashes": { + "SHA-256": "0969de02ecf8a5f003e3f6d063d848c8a193aada092623f8ce408c15bcb5f038" + } + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--9a1f834d-2506-5367-baec-7aa63996ac43", + "name": "foo.zip", + "hashes": { + "SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f" + }, + "mime_type": "application/zip", + "extensions": { + "archive-ext": { + "contains_refs": [ + "file--019fde1c-94ca-5967-8b3c-a906a51d87ac", + "file--94fc2163-dec3-5715-b824-6e689c4de865", + "file--d07ff290-d7e0-545b-a2ff-04602a9e0b73" + ] + } + } + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--73c4cd13-7206-5100-88ef-822c42d3f02c", + "hashes": { + "SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f" + }, + "extensions": { + "ntfs-ext": { + "alternate_data_streams": [ + { + "name": "second.stream", + "size": 25536 + } + ] + } + } + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--ec3415cc-5f4f-5ec8-bdb1-6f86996ae66d", + "name": "example.pdf", + "extensions": { + "pdf-ext": { + "version": "1.7", + "document_info_dict": { + "Title": "Sample document", + "Author": "Adobe Systems Incorporated", + "Creator": "Adobe FrameMaker 5.5.3 for Power Macintosh", + "Producer": "Acrobat Distiller 3.01 for Power Macintosh", + "CreationDate": "20070412090123-02" + }, + "pdfid0": "DFCE52BD827ECF765649852119D", + "pdfid1": "57A1E0F9ED2AE523E313C" + } + } + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--c7d1e135-8b34-549a-bb47-302f5cf998ed", + "name": "picture.jpg", + "hashes": { + "SHA-256": "4bac27393bdd9777ce02453256c5577cd02275510b2227f473d03f533924f877" + }, + "extensions": { + "raster-image-ext": { + "exif_tags": { + "Make": "Nikon", + "Model": "D7000", + "XResolution": 4928, + "YResolution": 3264 + } + } + } + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--fb0419a8-f09c-57f8-be64-71a80417591c", + "name": "example.exe", + "extensions": { + "windows-pebinary-ext": { + "pe_type": "exe", + "machine_hex": "014c", + "number_of_sections": 4, + "time_date_stamp": "2016-01-22T12:31:12Z", + "pointer_to_symbol_table_hex": "74726144", + "number_of_symbols": 4542568, + "size_of_optional_header": 224, + "characteristics_hex": "818f", + "optional_header": { + "magic_hex": "010b", + "major_linker_version": 2, + "minor_linker_version": 25, + "size_of_code": 512, + "size_of_initialized_data": 283648, + "size_of_uninitialized_data": 0, + "address_of_entry_point": 4096, + "base_of_code": 4096, + "base_of_data": 8192, + "image_base": 14548992, + "section_alignment": 4096, + "file_alignment": 4096, + "major_os_version": 1, + "minor_os_version": 0, + "major_image_version": 0, + "minor_image_version": 0, + "major_subsystem_version": 4, + "minor_subsystem_version": 0, + "win32_version_value_hex": "00", + "size_of_image": 299008, + "size_of_headers": 4096, + "checksum_hex": "00", + "subsystem_hex": "03", + "dll_characteristics_hex": "00", + "size_of_stack_reserve": 100000, + "size_of_stack_commit": 8192, + "size_of_heap_reserve": 100000, + "size_of_heap_commit": 4096, + "loader_flags_hex": "abdbffde", + "number_of_rva_and_sizes": 3758087646 + }, + "sections": [ + { + "name": "CODE", + "entropy": 0.061089 + }, + { + "name": "DATA", + "entropy": 7.980693 + }, + { + "name": "NicolasB", + "entropy": 0.607433 + }, + { + "name": ".idata", + "entropy": 0.607433 + } + ] + } + } + }, + { + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--ff26c055-6336-5bc5-b98d-13d6226742dd", + "value": "198.51.100.3" + }, + { + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--5853f6a4-638f-5b4e-9b0f-ded361ae3812", + "value": "198.51.100.0/24" + }, + { + "type": "ipv6-addr", + "spec_version": "2.1", + "id": "ipv6-addr--1e61d36c-a16c-53b7-a80f-2a00161c96b1", + "value": "2001:0db8:85a3:0000:0000:8a2e:0370:7334" + }, + { + "type": "ipv6-addr", + "spec_version": "2.1", + "id": "ipv6-addr--5daf7456-8863-5481-9d42-237d477697f4", + "value": "2001:0db8::/96" + }, + { + "type": "mac-addr", + "spec_version": "2.1", + "id": "mac-addr--65cfcf98-8a6e-5a1b-8f61-379ac4f92d00", + "value": "d2:fb:49:24:37:18" + }, + { + "type": "mutex", + "spec_version": "2.1", + "id": "mutex--eba44954-d4e4-5d3b-814c-2b17dd8de300", + "name": "__CLEANSWEEP__" + }, + { + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--4d22aae0-2bf9-5427-8819-e4f6abf20a53", + "value": "198.51.100.2" + }, + { + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--ff26c055-6336-5bc5-b98d-13d6226742dd", + "value": "198.51.100.3" + }, + { + "type": "network-traffic", + "spec_version": "2.1", + "id": "network-traffic--2568d22a-8998-58eb-99ec-3c8ca74f527d", + "src_ref": "ipv4-addr--4d22aae0-2bf9-5427-8819-e4f6abf20a53", + "dst_ref": "ipv4-addr--ff26c055-6336-5bc5-b98d-13d6226742dd", + "protocols": [ + "tcp" + ] + }, + { + "type": "domain-name", + "spec_version": "2.1", + "id": "domain-name--3c10e93f-798e-5a26-a0c1-08156efab7f5", + "value": "example.com" + }, +{ + "type": "network-traffic", + "spec_version": "2.1", + "id": "network-traffic--15a157a8-26e3-56e0-820b-0c2a8e553a2c", + "dst_ref": "domain-name--3c10e93f-798e-5a26-a0c1-08156efab7f5", + "protocols": [ + "ipv4", + "tcp", + "http" + ] +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--e42c19c8-f9fe-5ae9-9fc8-22c398f78fb7", + "value": "203.0.113.1" +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--03b708d9-7761-5523-ab75-5ea096294a68", + "value": "203.0.113.5" +}, +{ + "type": "network-traffic", + "spec_version": "2.1", + "id": "network-traffic--630d7bb1-0bbc-53a6-a6d4-f3c2d35c2734", + "src_ref": "ipv4-addr--e42c19c8-f9fe-5ae9-9fc8-22c398f78fb7", + "dst_ref": "ipv4-addr--03b708d9-7761-5523-ab75-5ea096294a68", + "protocols": [ + "ipv4", + "tcp" + ], + "src_byte_count": 147600, + "src_packets": 100, + "ipfix": { + "minimumIpTotalLength": 32, + "maximumIpTotalLength": 2556 + } +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--4d22aae0-2bf9-5427-8819-e4f6abf20a53", + "value": "198.51.100.2" +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--e42c19c8-f9fe-5ae9-9fc8-22c398f78fb7", + "value": "203.0.113.1" +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--ffe65ce3-bf2a-577c-bb7e-947d39198637", + "value": "203.0.113.2" +}, +{ + "type": "network-traffic", + "spec_version": "2.1", + "id": "network-traffic--ac267abc-1a41-536d-8e8d-98458d9bf491", + "src_ref": "ipv4-addr--4d22aae0-2bf9-5427-8819-e4f6abf20a53", + "dst_ref": "ipv4-addr--e42c19c8-f9fe-5ae9-9fc8-22c398f78fb7", + "src_port": 2487, + "dst_port": 1723, + "protocols": [ + "ipv4", + "pptp" + ], + "src_byte_count": 35779, + "dst_byte_count": 935750, + "encapsulates_refs": [ + "network-traffic--53e0bf48-2eee-5c03-8bde-ed7049d2c0a3" + ] +}, +{ + "type": "network-traffic", + "spec_version": "2.1", + "id": "network-traffic--53e0bf48-2eee-5c03-8bde-ed7049d2c0a3", + "src_ref": "ipv4-addr--4d22aae0-2bf9-5427-8819-e4f6abf20a53", + "dst_ref": "ipv4-addr--ffe65ce3-bf2a-577c-bb7e-947d39198637", + "src_port": 24678, + "dst_port": 80, + "protocols": [ + "ipv4", + "tcp", + "http" + ], + "src_packets": 14356, + "dst_packets": 14356, + "encapsulated_by_ref": "network-traffic--ac267abc-1a41-536d-8e8d-98458d9bf491" +}, + { + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--e42c19c8-f9fe-5ae9-9fc8-22c398f78fb7", + "value": "203.0.113.1" + }, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--f2d3c796-6c1a-5c4f-8516-d4db54727f89", + "value": "198.51.100.34" +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--bb884ffe-f2e4-56bb-a0c3-21f6711cb649", + "value": "198.51.100.54" +}, +{ + "type": "network-traffic", + "spec_version": "2.1", + "id": "network-traffic--b4a8c150-e214-57a3-9017-e85dfa345f46", + "src_ref": "ipv4-addr--e42c19c8-f9fe-5ae9-9fc8-22c398f78fb7", + "dst_ref": "ipv4-addr--f2d3c796-6c1a-5c4f-8516-d4db54727f89", + "src_port": 2487, + "dst_port": 53, + "protocols": [ + "ipv4", + "udp", + "dns" + ], + "src_byte_count": 35779, + "dst_byte_count": 935750, + "encapsulates_refs": [ + "network-traffic--65a6016d-a91c-5781-baad-178cd55f01d4" + ] +}, +{ + "type": "network-traffic", + "spec_version": "2.1", + "id": "network-traffic--65a6016d-a91c-5781-baad-178cd55f01d4", + "src_ref": "ipv4-addr--f2d3c796-6c1a-5c4f-8516-d4db54727f89", + "dst_ref": "ipv4-addr--bb884ffe-f2e4-56bb-a0c3-21f6711cb649", + "src_port": 24678, + "dst_port": 443, + "protocols": [ + "ipv4", + "tcp", + "ssl", + "http" + ], + "src_packets": 14356, + "dst_packets": 14356, + "encapsulated_by_ref": "network-traffic--b4a8c150-e214-57a3-9017-e85dfa345f46" +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--6da8dad3-4de3-5f8e-ab23-45d0b8f12f16", + "value": "198.51.100.53" + +}, +{ + "type": "network-traffic", + "spec_version": "2.1", + "id": "network-traffic--f8ae967a-3dc3-5cdf-8f94-8505abff00c2", + "dst_ref": "ipv4-addr--6da8dad3-4de3-5f8e-ab23-45d0b8f12f16", + "protocols": [ + "tcp", + "http" + ], + "extensions": { + "http-request-ext": { + "request_method": "get", + "request_value": "/download.html", + "request_version": "http/1.1", + "request_header": { + "Accept-Encoding": [ + "gzip,deflate" + ], + "User-Agent": [ + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113" + ], + "Host": [ + "www.example.com" + ] + } + } + } +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--d7177770-fc12-586b-9244-426596a7008e", + "value": "198.51.100.9" +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--03b708d9-7761-5523-ab75-5ea096294a68", + "value": "203.0.113.5" +}, +{ + "type": "network-traffic", + "spec_version": "2.1", + "id": "network-traffic--e7a939ca-78c6-5f27-8ae0-4ad112454626", + "src_ref": "ipv4-addr--d7177770-fc12-586b-9244-426596a7008e", + "dst_ref": "ipv4-addr--03b708d9-7761-5523-ab75-5ea096294a68", + "protocols": [ + "icmp" + ], + "extensions": { + "icmp-ext": { + "icmp_type_hex": "08", + "icmp_code_hex": "00" + } + } +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--4d22aae0-2bf9-5427-8819-e4f6abf20a53", + "value": "198.51.100.2" +}, +{ + "type": "network-traffic", + "spec_version": "2.1", + "id": "network-traffic--c95e972a-20a4-5307-b00d-b8393faf02c5", + "src_ref": "ipv4-addr--4d22aae0-2bf9-5427-8819-e4f6abf20a53", + "src_port": 223, + "protocols": [ + "ip", + "tcp" + ], + "extensions": { + "socket-ext": { + "is_listening": true, + "address_family": "AF_INET", + "socket_type": "SOCK_STREAM" + } + } +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--89830c10-2e94-57fa-8ca6-e0537d2719d1", + "value": "198.51.100.5" +}, +{ + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--45f4c6fb-2d7d-576a-a571-edc78d899a72", + "value": "198.51.100.6" +}, +{ + "type": "network-traffic", + "spec_version": "2.1", + "id": "network-traffic--09ca55c3-97e5-5966-bad0-1d41d557ae13", + "src_ref": "ipv4-addr--89830c10-2e94-57fa-8ca6-e0537d2719d1", + "dst_ref": "ipv4-addr--45f4c6fb-2d7d-576a-a571-edc78d899a72", + "src_port": 3372, + "dst_port": 80, + "protocols": [ + "tcp" + ], + "extensions": { + "tcp-ext": { + "src_flags_hex": "00000002" + } + } +}, +{ + "type": "file", + "spec_version": "2.1", + "id": "file--edb1ebee-4387-41cc-943b-f94fd491118c", + "name": "gedit-bin", + "hashes": { + "SHA-256": "aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f" + } +}, +{ + "type": "process", + "spec_version": "2.1", + "id": "process--d2ec5aab-808d-4492-890a-3c1a1e3cb06e", + "pid": 1221, + "created_time": "2016-01-20T14:11:25.55Z", + "command_line": "./gedit-bin --new-window", + "image_ref": "file--e04f22d1-be2c-59de-add8-10f61d15fe20" +}, +{ + "type": "process", + "spec_version": "2.1", + "id": "process--de02a3e4-4b96-460a-b799-684347004444", + "pid": 314, + "extensions": { + "windows-process-ext": { + "aslr_enabled": true, + "dep_enabled": true, + "priority": "HIGH_PRIORITY_CLASS", + "owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309" + } + } +}, +{ + "type": "file", + "spec_version": "2.1", + "id": "file--4b9a516b-4974-4ff8-a50d-a8b8d552ce1f", + "hashes": { + "SHA-256": "bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c" + }, + "name": "sirvizio.exe" +}, +{ + "type": "process", + "spec_version": "2.1", + "id": "process--70b17c6c-93e5-4c80-8683-5a4d4e51f2c1", + "pid": 2217, + "command_line": "C:\\Windows\\System32\\sirvizio.exe /s", + "image_ref": "file--3916128d-69af-5525-be7a-99fac2383a59", + "extensions": { + "windows-service-ext": { + "service_name": "sirvizio", + "display_name": "Sirvizio", + "start_type": "SERVICE_AUTO_START", + "service_type": "SERVICE_WIN32_OWN_PROCESS", + "service_status": "SERVICE_RUNNING" + } + } +}, +{ + "type": "software", + "spec_version": "2.1", + "id": "software--a1827f6d-ca53-5605-9e93-4316cd22a00a", + "name": "Word", + "cpe": "cpe:2.3:a:microsoft:word:2000:*:*:*:*:*:*:*", + "version": "2002", + "vendor": "Microsoft" +}, +{ + "type": "url", + "spec_version": "2.1", + "id": "url--c1477287-23ac-5971-a010-5c287877fa60", + "value": "https://example.com/research/index.html" +}, +{ + "type": "user-account", + "spec_version": "2.1", + "id": "user-account--0d5b424b-93b8-5cd8-ac36-306e1789d63c", + "user_id": "1001", + "account_login": "jdoe", + "account_type": "unix", + "display_name": "John Doe", + "is_service_account": false, + "is_privileged": false, + "can_escalate_privs": true, + "account_created": "2016-01-20T12:31:12Z", + "credential_last_changed": "2016-01-20T14:27:43Z", + "account_first_login": "2016-01-20T14:26:07Z", + "account_last_login": "2016-07-22T16:08:28Z" +}, +{ + "type": "user-account", + "spec_version": "2.1", + "id": "user-account--9bd3afcf-deee-54f9-83e2-520653cb6bba", + "user_id": "thegrugq_ebooks", + "account_login": "thegrugq_ebooks", + "account_type": "twitter", + "display_name": "the grugq" + }, + { + "type": "user-account", + "spec_version": "2.1", + "id": "user-account--0d5b424b-93b8-5cd8-ac36-306e1789d63c", + "user_id": "1001", + "account_login": "jdoe", + "account_type": "unix", + "display_name": "John Doe", + "is_service_account": false, + "is_privileged": false, + "can_escalate_privs": true, + "extensions": { + "unix-account-ext": { + "gid": 1001, + "groups": ["wheel"], + "home_dir": "/home/jdoe", + "shell": "/bin/bash" + } + } +}, +{ + "type": "windows-registry-key", + "spec_version": "2.1", + "id": "windows-registry-key--9d60798d-4e3e-5fe4-af8a-0e4986f0f90b", + "key": "HKEY_LOCAL_MACHINE\\System\\Foo\\Bar" + }, + { + "type": "windows-registry-key", + "spec_version": "2.1", + "id": "windows-registry-key--2ba37ae7-2745-5082-9dfd-9486dad41016", + "key": "hkey_local_machine\\system\\bar\\foo", + "values": [ + { + "name": "Foo", + "data": "qwerty", + "data_type": "REG_SZ" + }, + { + "name": "Bar", + "data": "42", + "data_type": "REG_DWORD" + } + ] +}, +{ + "type": "x509-certificate", + "spec_version": "2.1", + "id": "x509-certificate--463d7b2a-8516-5a50-a3d7-6f801465d5de", + "issuer": "C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/emailAddress=server-certs@thawte.com", + "validity_not_before": "2016-03-12T12:00:00Z", + "validity_not_after": "2016-08-21T12:00:00Z", + "subject": "C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=baccala@freesoft.org", + "serial_number": "36:f7:d4:32:f4:ab:70:ea:d3:ce:98:6e:ea:99:93:49:32:0a:b7:06" +}, +{ + "type":"x509-certificate", + "spec_version": "2.1", + "id": "x509-certificate--b595eaf0-0b28-5dad-9e8e-0fab9c1facc9", + "issuer":"C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/emailAddress=server-certs@thawte.com", + "validity_not_before":"2016-03-12T12:00:00Z", + "validity_not_after":"2016-08-21T12:00:00Z", + "subject":"C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=baccala@freesoft.org", + "serial_number": "02:08:87:83:f2:13:58:1f:79:52:1e:66:90:0a:02:24:c9:6b:c7:dc", + "x509_v3_extensions":{ + "basic_constraints":"critical,CA:TRUE, pathlen:0", + "name_constraints":"permitted;IP:192.168.0.0/255.255.0.0", + "policy_constraints":"requireExplicitPolicy:3", + "key_usage":"critical, keyCertSign", + "extended_key_usage":"critical,codeSigning,1.2.3.4", + "subject_key_identifier":"hash", + "authority_key_identifier":"keyid,issuer", + "subject_alternative_name":"email:my@other.address,RID:1.2.3.4", + "issuer_alternative_name":"issuer:copy", + "crl_distribution_points":"URI:http://myhost.com/myca.crl", + "inhibit_any_policy":"2", + "private_key_usage_period_not_before":"2016-03-12T12:00:00Z", + "private_key_usage_period_not_after":"2018-03-12T12:00:00Z", + "certificate_policies":"1.2.4.5, 1.1.3.4" + } +} +] From fa8c95bba783c9dce8e2c56391077aee22767553 Mon Sep 17 00:00:00 2001 From: Rich Piazza Date: Tue, 20 Aug 2024 11:07:13 -0400 Subject: [PATCH 09/13] flaky2 --- determinsitic-id-checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/determinsitic-id-checker.py b/determinsitic-id-checker.py index 67a9d8a2..c657af20 100644 --- a/determinsitic-id-checker.py +++ b/determinsitic-id-checker.py @@ -14,4 +14,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() From d2d7161fb54a7c231ccb8d3495ff1af46dc931bb Mon Sep 17 00:00:00 2001 From: Ming Fang Date: Thu, 19 Sep 2024 14:41:50 -0400 Subject: [PATCH 10/13] Fix issue #586. --- stix2/v21/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stix2/v21/common.py b/stix2/v21/common.py index 55c4a05d..103fff7d 100644 --- a/stix2/v21/common.py +++ b/stix2/v21/common.py @@ -77,7 +77,7 @@ class GranularMarking(_STIXBase21): def _check_object_constraints(self): super(GranularMarking, self)._check_object_constraints() self._check_at_least_one_property(['lang', 'marking_ref']) - + self._check_mutually_exclusive_properties(['lang', 'marking_ref']) class LanguageContent(_STIXBase21): """For more detailed information on this object's properties, see From 6299ff9b38d6d6543930654a61bb4e27f7c00fcc Mon Sep 17 00:00:00 2001 From: Ming Fang Date: Fri, 20 Sep 2024 15:54:41 -0400 Subject: [PATCH 11/13] Add v21 test for GranularMarking to close #586. --- stix2/test/v21/test_markings.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/stix2/test/v21/test_markings.py b/stix2/test/v21/test_markings.py index d3fd11bb..47925499 100644 --- a/stix2/test/v21/test_markings.py +++ b/stix2/test/v21/test_markings.py @@ -170,6 +170,18 @@ def test_granular_example_with_bad_selector(): assert str(excinfo.value) == "Invalid value for GranularMarking 'selectors': must adhere to selector syntax." +def test_granular_marking_mutual_exclusion_error(): + with pytest.raises(stix2.exceptions.MutuallyExclusivePropertiesError) as excinfo: + stix2.v21.GranularMarking( + lang="en", + marking_ref=stix2.TLP_GREEN, + selectors=["foo"] + ) + assert excinfo.value.cls == stix2.v21.GranularMarking + assert excinfo.value.properties == ["lang", "marking_ref"] + assert 'are mutually exclusive' in str(excinfo.value) + + def test_campaign_with_granular_markings_example(): campaign = stix2.v21.Campaign( id="campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f", From 12ada44a63bfc5bbcab1687e81602223c7cecebe Mon Sep 17 00:00:00 2001 From: Ming Fang Date: Tue, 24 Sep 2024 17:10:24 -0400 Subject: [PATCH 12/13] Add trailing comma expected by the pre-commit hook. --- stix2/test/v21/test_markings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stix2/test/v21/test_markings.py b/stix2/test/v21/test_markings.py index 47925499..0b2e950e 100644 --- a/stix2/test/v21/test_markings.py +++ b/stix2/test/v21/test_markings.py @@ -175,7 +175,7 @@ def test_granular_marking_mutual_exclusion_error(): stix2.v21.GranularMarking( lang="en", marking_ref=stix2.TLP_GREEN, - selectors=["foo"] + selectors=["foo"], ) assert excinfo.value.cls == stix2.v21.GranularMarking assert excinfo.value.properties == ["lang", "marking_ref"] From a2beb46f35ea070b483c61e2bc94e66ba97c440e Mon Sep 17 00:00:00 2001 From: Ming Fang Date: Wed, 25 Sep 2024 11:53:29 -0400 Subject: [PATCH 13/13] Add extra blank line to make pre-commit happy. --- stix2/v21/common.py | 1 + 1 file changed, 1 insertion(+) diff --git a/stix2/v21/common.py b/stix2/v21/common.py index 103fff7d..ca795e02 100644 --- a/stix2/v21/common.py +++ b/stix2/v21/common.py @@ -79,6 +79,7 @@ def _check_object_constraints(self): self._check_at_least_one_property(['lang', 'marking_ref']) self._check_mutually_exclusive_properties(['lang', 'marking_ref']) + class LanguageContent(_STIXBase21): """For more detailed information on this object's properties, see `the STIX 2.1 specification `__.