txt2detection 1.0.8__tar.gz → 1.0.10__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of txt2detection might be problematic. Click here for more details.

Files changed (63) hide show
  1. {txt2detection-1.0.8 → txt2detection-1.0.10}/.github/workflows/run-tests.yml +4 -0
  2. {txt2detection-1.0.8 → txt2detection-1.0.10}/PKG-INFO +6 -8
  3. {txt2detection-1.0.8 → txt2detection-1.0.10}/README.md +5 -7
  4. {txt2detection-1.0.8 → txt2detection-1.0.10}/pyproject.toml +1 -1
  5. txt2detection-1.0.10/tests/files/sigma-rule-attack-enterprise.yml +27 -0
  6. txt2detection-1.0.10/tests/files/sigma-rule-attack-flow.yml +25 -0
  7. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-custom-tags.yml +1 -1
  8. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-master.yml +1 -1
  9. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-no-description.yml +0 -1
  10. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-no-level.yml +0 -1
  11. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-no-license.yml +0 -1
  12. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-no-status.yml +0 -1
  13. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-observables.yml +0 -1
  14. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/manual-tests/README.md +30 -1
  15. txt2detection-1.0.10/tests/src/conftest.py +18 -0
  16. txt2detection-1.0.10/tests/src/test_attack_flow.py +519 -0
  17. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/src/test_bundler.py +16 -11
  18. txt2detection-1.0.10/txt2detection/__main__.py +347 -0
  19. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/ai_extractor/base.py +41 -13
  20. txt2detection-1.0.10/txt2detection/ai_extractor/models.py +34 -0
  21. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/ai_extractor/openai.py +1 -3
  22. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/ai_extractor/openrouter.py +4 -4
  23. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/ai_extractor/prompts.py +130 -3
  24. txt2detection-1.0.10/txt2detection/attack_flow.py +231 -0
  25. txt2detection-1.0.10/txt2detection/bundler.py +388 -0
  26. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/credential_checker.py +11 -9
  27. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/models.py +11 -0
  28. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/observables.py +0 -1
  29. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/utils.py +24 -12
  30. txt2detection-1.0.8/txt2detection/__main__.py +0 -196
  31. txt2detection-1.0.8/txt2detection/bundler.py +0 -296
  32. {txt2detection-1.0.8 → txt2detection-1.0.10}/.env.example +0 -0
  33. {txt2detection-1.0.8 → txt2detection-1.0.10}/.env.markdown +0 -0
  34. {txt2detection-1.0.8 → txt2detection-1.0.10}/.github/workflows/create-release.yml +0 -0
  35. {txt2detection-1.0.8 → txt2detection-1.0.10}/.gitignore +0 -0
  36. {txt2detection-1.0.8 → txt2detection-1.0.10}/LICENSE +0 -0
  37. {txt2detection-1.0.8 → txt2detection-1.0.10}/config/detection_languages.yaml +0 -0
  38. {txt2detection-1.0.8 → txt2detection-1.0.10}/docs/README.md +0 -0
  39. {txt2detection-1.0.8 → txt2detection-1.0.10}/docs/txt2detection.png +0 -0
  40. {txt2detection-1.0.8 → txt2detection-1.0.10}/requirements.txt +0 -0
  41. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/CVE-2024-56520.txt +0 -0
  42. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/EC2-exfil.txt +0 -0
  43. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/observables.txt +0 -0
  44. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-existing-related.yml +0 -0
  45. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-no-author.yml +0 -0
  46. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-no-date.yml +0 -0
  47. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-no-tags.yml +0 -0
  48. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-no-title.yml +0 -0
  49. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/files/sigma-rule-one-date.yml +0 -0
  50. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/src/__init__.py +0 -0
  51. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/src/requirements.txt +0 -0
  52. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/src/test_main.py +0 -0
  53. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/src/test_main_run_txt2detction.py +0 -0
  54. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/src/test_models.py +0 -0
  55. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/src/test_observables.py +0 -0
  56. {txt2detection-1.0.8 → txt2detection-1.0.10}/tests/src/test_utils.py +0 -0
  57. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/__init__.py +0 -0
  58. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/ai_extractor/__init__.py +0 -0
  59. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/ai_extractor/anthropic.py +0 -0
  60. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/ai_extractor/deepseek.py +0 -0
  61. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/ai_extractor/gemini.py +0 -0
  62. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection/ai_extractor/utils.py +0 -0
  63. {txt2detection-1.0.8 → txt2detection-1.0.10}/txt2detection.py +0 -0
@@ -33,6 +33,10 @@ jobs:
33
33
  run: |
34
34
  echo > .env
35
35
  echo "INPUT_TOKEN_LIMIT=1000" >> .env
36
+ echo "CTIBUTLER_BASE_URL=https://api.ctibutler.com/" >> .env
37
+ echo "CTIBUTLER_API_KEY=${{ secrets.CTIBUTLER_API_KEY }}" >> .env
38
+ echo "VULMATCH_BASE_URL=https://api.vulmatch.com/" >> .env
39
+ echo "VULMATCH_API_KEY=${{ secrets.VULMATCH_API_KEY }}" >> .env
36
40
 
37
41
  - name: Run Tests
38
42
  id: run_tests
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: txt2detection
3
- Version: 1.0.8
3
+ Version: 1.0.10
4
4
  Summary: A command line tool that takes a txt file containing threat intelligence and turns it into a detection rule.
5
5
  Project-URL: Homepage, https://github.com/muchdogesec/txt2detection
6
6
  Project-URL: Issues, https://github.com/muchdogesec/txt2detection/issues
@@ -72,12 +72,6 @@ txt2detection allows a user to enter some threat intelligence as a file to consi
72
72
  2. Based on the user input, AI prompts structured and sent to produce an intelligence rule
73
73
  3. Rules converted into STIX objects
74
74
 
75
- ## tl;dr
76
-
77
- [![txt2detection](https://img.youtube.com/vi/uJWXYKyu3Xg/0.jpg)](https://www.youtube.com/watch?v=uJWXYKyu3Xg)
78
-
79
- [Watch the demo](https://www.youtube.com/watch?v=uJWXYKyu3Xg).
80
-
81
75
  ## Usage
82
76
 
83
77
  ### Setup
@@ -162,12 +156,14 @@ Use this mode to generate a set of rules from an input text file;
162
156
  * `--license` (optional): [License of the rule according the SPDX ID specification](https://spdx.org/licenses/). Will be added to the rule.
163
157
  * `--reference_urls` (optional): A list of URLs to be added as `references` in the Sigma Rule property and in the `external_references` property of the Indicator and Report STIX object created. e.g `"https://www.google.com/" "https://www.facebook.com/"`
164
158
  * `--external_refs` (optional): txt2detection will automatically populate the `external_references` of the report object it creates for the input. You can use this value to add additional objects to `external_references`. Note, you can only add `source_name` and `external_id` values currently. Pass as `source_name=external_id`. e.g. `--external_refs txt2stix=demo1 source=id` would create the following objects under the `external_references` property: `{"source_name":"txt2stix","external_id":"demo1"},{"source_name":"source","external_id":"id"}`
165
- * `ai_provider` (required): defines the `provider:model` to be used to generate the rule. Select one option. Currently supports:
159
+ * `--ai_provider` (required): defines the `provider:model` to be used to generate the rule. Select one option. Currently supports:
166
160
  * Provider (env var required `OPENROUTER_API_KEY`): `openrouter:`, providers/models `openai/gpt-4o`, `deepseek/deepseek-chat` ([More here](https://openrouter.ai/models))
167
161
  * Provider (env var required `OPENAI_API_KEY`): `openai:`, models e.g.: `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo`, `gpt-4` ([More here](https://platform.openai.com/docs/models))
168
162
  * Provider (env var required `ANTHROPIC_API_KEY`): `anthropic:`, models e.g.: `claude-3-5-sonnet-latest`, `claude-3-5-haiku-latest`, `claude-3-opus-latest` ([More here](https://docs.anthropic.com/en/docs/about-claude/models))
169
163
  * Provider (env var required `GOOGLE_API_KEY`): `gemini:models/`, models: `gemini-1.5-pro-latest`, `gemini-1.5-flash-latest` ([More here](https://ai.google.dev/gemini-api/docs/models/gemini))
170
164
  * Provider (env var required `DEEPSEEK_API_KEY`): `deepseek:`, models `deepseek-chat` ([More here](https://api-docs.deepseek.com/quick_start/pricing))
165
+ * `--ai_create_attack_flow` (boolean): passing this flag will also prompt the AI model (the same entered for `--ai_provider`, default `false`) to generate an [Attack Flow](https://center-for-threat-informed-defense.github.io/attack-flow/) for the MITRE ATT&CK tags to define the logical order in which they are being described. Note, Sigma currently supports ATT&CK Enterprise only.
166
+ * `--ai_create_attack_navigator_layer` (boolean, default `false`): passing this flag will generate a [MITRE ATT&CK Navigator layer](https://mitre-attack.github.io/attack-navigator/) for MITRE ATT&CK tags. Note, Sigma currently supports ATT&CK Enterprise only. You don't need to pass this if `--ai_create_attack_flow` is set to `true` (as this mode relies on this setting being true)
171
167
 
172
168
  Note, in this mode, the following values will be automatically assigned to the rule
173
169
 
@@ -194,6 +190,8 @@ Note, in this mode you should be aware of a few things;
194
190
  * `--external_refs` (optional): txt2detection will automatically populate the `external_references` of the report object it creates for the input. You can use this value to add additional objects to `external_references`. Note, you can only add `source_name` and `external_id` values currently. Pass as `source_name=external_id`. e.g. `--external_refs txt2stix=demo1 source=id` would create the following objects under the `external_references` property: `{"source_name":"txt2stix","external_id":"demo1"},{"source_name":"source","external_id":"id"}`
195
191
  * `status` (optional): either `stable`, `test`, `experimental`, `deprecated`, `unsupported`. If passed, will overwrite any existing `status` recorded in the rule
196
192
  * `level` (optional): either `informational`, `low`, `medium`, `high`, `critical`. If passed, will overwrite any existing `level` recorded in the rule
193
+ * `--ai_create_attack_flow` (boolean): passing this flag will also prompt the AI model (the same entered for `--ai_provider`, default `false`) to generate an [Attack Flow](https://center-for-threat-informed-defense.github.io/attack-flow/) for the MITRE ATT&CK tags to define the logical order in which they are being described. Note, Sigma currently supports ATT&CK Enterprise only.
194
+ * `--ai_create_attack_navigator_layer` (boolean, default `false`): passing this flag will generate a [MITRE ATT&CK Navigator layer](https://mitre-attack.github.io/attack-navigator/) for MITRE ATT&CK tags. Note, Sigma currently supports ATT&CK Enterprise only. You don't need to pass this if `--ai_create_attack_flow` is set to `true` (as this mode relies on this setting being true)
197
195
 
198
196
  ### A note on observable extraction
199
197
 
@@ -31,12 +31,6 @@ txt2detection allows a user to enter some threat intelligence as a file to consi
31
31
  2. Based on the user input, AI prompts structured and sent to produce an intelligence rule
32
32
  3. Rules converted into STIX objects
33
33
 
34
- ## tl;dr
35
-
36
- [![txt2detection](https://img.youtube.com/vi/uJWXYKyu3Xg/0.jpg)](https://www.youtube.com/watch?v=uJWXYKyu3Xg)
37
-
38
- [Watch the demo](https://www.youtube.com/watch?v=uJWXYKyu3Xg).
39
-
40
34
  ## Usage
41
35
 
42
36
  ### Setup
@@ -121,12 +115,14 @@ Use this mode to generate a set of rules from an input text file;
121
115
  * `--license` (optional): [License of the rule according the SPDX ID specification](https://spdx.org/licenses/). Will be added to the rule.
122
116
  * `--reference_urls` (optional): A list of URLs to be added as `references` in the Sigma Rule property and in the `external_references` property of the Indicator and Report STIX object created. e.g `"https://www.google.com/" "https://www.facebook.com/"`
123
117
  * `--external_refs` (optional): txt2detection will automatically populate the `external_references` of the report object it creates for the input. You can use this value to add additional objects to `external_references`. Note, you can only add `source_name` and `external_id` values currently. Pass as `source_name=external_id`. e.g. `--external_refs txt2stix=demo1 source=id` would create the following objects under the `external_references` property: `{"source_name":"txt2stix","external_id":"demo1"},{"source_name":"source","external_id":"id"}`
124
- * `ai_provider` (required): defines the `provider:model` to be used to generate the rule. Select one option. Currently supports:
118
+ * `--ai_provider` (required): defines the `provider:model` to be used to generate the rule. Select one option. Currently supports:
125
119
  * Provider (env var required `OPENROUTER_API_KEY`): `openrouter:`, providers/models `openai/gpt-4o`, `deepseek/deepseek-chat` ([More here](https://openrouter.ai/models))
126
120
  * Provider (env var required `OPENAI_API_KEY`): `openai:`, models e.g.: `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo`, `gpt-4` ([More here](https://platform.openai.com/docs/models))
127
121
  * Provider (env var required `ANTHROPIC_API_KEY`): `anthropic:`, models e.g.: `claude-3-5-sonnet-latest`, `claude-3-5-haiku-latest`, `claude-3-opus-latest` ([More here](https://docs.anthropic.com/en/docs/about-claude/models))
128
122
  * Provider (env var required `GOOGLE_API_KEY`): `gemini:models/`, models: `gemini-1.5-pro-latest`, `gemini-1.5-flash-latest` ([More here](https://ai.google.dev/gemini-api/docs/models/gemini))
129
123
  * Provider (env var required `DEEPSEEK_API_KEY`): `deepseek:`, models `deepseek-chat` ([More here](https://api-docs.deepseek.com/quick_start/pricing))
124
+ * `--ai_create_attack_flow` (boolean): passing this flag will also prompt the AI model (the same entered for `--ai_provider`, default `false`) to generate an [Attack Flow](https://center-for-threat-informed-defense.github.io/attack-flow/) for the MITRE ATT&CK tags to define the logical order in which they are being described. Note, Sigma currently supports ATT&CK Enterprise only.
125
+ * `--ai_create_attack_navigator_layer` (boolean, default `false`): passing this flag will generate a [MITRE ATT&CK Navigator layer](https://mitre-attack.github.io/attack-navigator/) for MITRE ATT&CK tags. Note, Sigma currently supports ATT&CK Enterprise only. You don't need to pass this if `--ai_create_attack_flow` is set to `true` (as this mode relies on this setting being true)
130
126
 
131
127
  Note, in this mode, the following values will be automatically assigned to the rule
132
128
 
@@ -153,6 +149,8 @@ Note, in this mode you should be aware of a few things;
153
149
  * `--external_refs` (optional): txt2detection will automatically populate the `external_references` of the report object it creates for the input. You can use this value to add additional objects to `external_references`. Note, you can only add `source_name` and `external_id` values currently. Pass as `source_name=external_id`. e.g. `--external_refs txt2stix=demo1 source=id` would create the following objects under the `external_references` property: `{"source_name":"txt2stix","external_id":"demo1"},{"source_name":"source","external_id":"id"}`
154
150
  * `status` (optional): either `stable`, `test`, `experimental`, `deprecated`, `unsupported`. If passed, will overwrite any existing `status` recorded in the rule
155
151
  * `level` (optional): either `informational`, `low`, `medium`, `high`, `critical`. If passed, will overwrite any existing `level` recorded in the rule
152
+ * `--ai_create_attack_flow` (boolean): passing this flag will also prompt the AI model (the same entered for `--ai_provider`, default `false`) to generate an [Attack Flow](https://center-for-threat-informed-defense.github.io/attack-flow/) for the MITRE ATT&CK tags to define the logical order in which they are being described. Note, Sigma currently supports ATT&CK Enterprise only.
153
+ * `--ai_create_attack_navigator_layer` (boolean, default `false`): passing this flag will generate a [MITRE ATT&CK Navigator layer](https://mitre-attack.github.io/attack-navigator/) for MITRE ATT&CK tags. Note, Sigma currently supports ATT&CK Enterprise only. You don't need to pass this if `--ai_create_attack_flow` is set to `true` (as this mode relies on this setting being true)
156
154
 
157
155
  ### A note on observable extraction
158
156
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "txt2detection"
7
- version = "1.0.8"
7
+ version = "1.0.10"
8
8
  authors = [
9
9
  { name = "dogesec" }
10
10
  ]
@@ -0,0 +1,27 @@
1
+ title: Attack Navigator Enterprise
2
+ id: a18e76d1-f152-4b87-a552-d46f41afd637
3
+ status: test
4
+ description: Build an Attack Enterprise Navigator layer
5
+ references:
6
+ - https://www.dogesec.com
7
+ author: dogesec
8
+ date: 2020-01-01
9
+ modified: 2020-01-02
10
+ tags:
11
+ - tlp.clear
12
+ - attack.t1547
13
+ - attack.t1671
14
+ - attack.t1025
15
+ - attack.command-and-control
16
+ - attack.t1661 # will fail is mobile
17
+ logsource:
18
+ product: okta
19
+ service: okta
20
+ detection:
21
+ selection:
22
+ eventtype:
23
+ - policy.lifecycle.update
24
+ - policy.lifecycle.delete
25
+ condition: selection
26
+ level: low
27
+ license: MIT
@@ -0,0 +1,25 @@
1
+ title: Attack Flow demo
2
+ id: 7894eba6-b0e5-48d9-be52-26bf5a556e45
3
+ status: test
4
+ description: Build an Attack Flow from a Sigma Rule
5
+ references:
6
+ - https://www.dogesec.com
7
+ author: dogesec
8
+ date: 2020-01-01
9
+ modified: 2020-01-02
10
+ tags:
11
+ - tlp.clear
12
+ - attack.t1547
13
+ - attack.t1671
14
+ - attack.t1025
15
+ logsource:
16
+ product: okta
17
+ service: okta
18
+ detection:
19
+ selection:
20
+ eventtype:
21
+ - policy.lifecycle.update
22
+ - policy.lifecycle.delete
23
+ condition: selection
24
+ level: low
25
+ license: MIT
@@ -11,7 +11,7 @@ modified: 2022-10-09
11
11
  tags:
12
12
  - tlp.red
13
13
  - attack.t1547
14
- - attack.command_and_control
14
+ - attack.command-and-control
15
15
  - cve.2024-56520
16
16
  - detection.xyz
17
17
  logsource:
@@ -11,7 +11,7 @@ modified: 2022-10-09
11
11
  tags:
12
12
  - tlp.red
13
13
  - attack.t1547
14
- - attack.command_and_control
14
+ - attack.command-and-control
15
15
  - cve.2024-56520
16
16
  logsource:
17
17
  product: okta
@@ -10,7 +10,6 @@ modified: 2022-10-09
10
10
  tags:
11
11
  - tlp.red
12
12
  - attack.t1547
13
- - attack.command_and_control
14
13
  - cve.2024-56520
15
14
  logsource:
16
15
  product: okta
@@ -11,7 +11,6 @@ modified: 2022-10-09
11
11
  tags:
12
12
  - tlp.red
13
13
  - attack.t1547
14
- - attack.command_and_control
15
14
  - cve.2024-56520
16
15
  logsource:
17
16
  product: okta
@@ -11,7 +11,6 @@ modified: 2022-10-09
11
11
  tags:
12
12
  - tlp.red
13
13
  - attack.t1547
14
- - attack.command_and_control
15
14
  - cve.2024-56520
16
15
  logsource:
17
16
  product: okta
@@ -10,7 +10,6 @@ modified: 2022-10-09
10
10
  tags:
11
11
  - tlp.red
12
12
  - attack.t1547
13
- - attack.command_and_control
14
13
  - cve.2024-56520
15
14
  logsource:
16
15
  product: okta
@@ -11,7 +11,6 @@ modified: 2022-10-09
11
11
  tags:
12
12
  - tlp.red
13
13
  - attack.t1547
14
- - attack.command_and_control
15
14
  - cve.2024-56520
16
15
  logsource:
17
16
  product: okta
@@ -445,4 +445,33 @@ python3 txt2detection.py sigma \
445
445
  --name "Overwrite status" \
446
446
  --status unsupported \
447
447
  --report_id d2d01afa-dc55-4a80-8d62-15d154450112
448
- ```
448
+ ```
449
+
450
+
451
+ ## Attack Flow
452
+
453
+ ```shell
454
+ python3 txt2detection.py sigma \
455
+ --sigma_file tests/files/sigma-rule-attack-flow.yml \
456
+ --name "Create ATT&CK Flow" \
457
+ --report_id 330e2030-1dc2-45e6-be13-9342b102621b \
458
+ --ai_provider openai:gpt-5 \
459
+ --ai_create_attack_flow
460
+ ```
461
+
462
+ ## Attack Navigator
463
+
464
+ ### Enterprise
465
+
466
+ ```shell
467
+ python3 txt2detection.py sigma \
468
+ --sigma_file tests/files/sigma-rule-attack-enterprise.yml \
469
+ --name "Attack Navigator Enterprise" \
470
+ --report_id a18e76d1-f152-4b87-a552-d46f41afd637 \
471
+ --ai_provider openai:gpt-5 \
472
+ --ai_create_attack_navigator_layer
473
+ ```
474
+
475
+ ### Mobile / ICS
476
+
477
+ Not currently supported by Sigma.
@@ -0,0 +1,18 @@
1
+ import pytest
2
+
3
+ from txt2detection.bundler import Bundler
4
+ from datetime import datetime
5
+
6
+
7
+
8
+ @pytest.fixture
9
+ def bundler_instance():
10
+ return Bundler(
11
+ name="Test Report",
12
+ identity=None,
13
+ tlp_level="red",
14
+ description="This is a test report.",
15
+ labels=["tlp.red", "test.test-var"],
16
+ created=datetime(2025, 1, 1),
17
+ report_id="74e36652-00f5-4dca-bf10-9f02fc996dcc",
18
+ )