txt2stix 0.0.4__tar.gz → 1.0.1__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.
Files changed (258) hide show
  1. {txt2stix-0.0.4 → txt2stix-1.0.1}/PKG-INFO +4 -3
  2. {txt2stix-0.0.4 → txt2stix-1.0.1}/pyproject.toml +8 -4
  3. {txt2stix-0.0.4 → txt2stix-1.0.1}/requirements.txt +38 -29
  4. txt2stix-1.0.1/tests/src/test_bundler.py +297 -0
  5. txt2stix-1.0.1/tests/src/test_main.py +338 -0
  6. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/src/test_run_txt2stix.py +89 -35
  7. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/src/test_utils.py +19 -0
  8. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/ai_extractor/base.py +4 -3
  9. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/ai_extractor/prompts.py +7 -1
  10. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/ai_extractor/utils.py +1 -0
  11. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/bundler.py +43 -10
  12. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/txt2stix.py +10 -13
  13. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/utils.py +4 -3
  14. txt2stix-0.0.4/tests/src/test_bundler.py +0 -105
  15. txt2stix-0.0.4/tests/src/test_main.py +0 -136
  16. {txt2stix-0.0.4 → txt2stix-1.0.1}/.env.example +0 -0
  17. {txt2stix-0.0.4 → txt2stix-1.0.1}/.env.markdown +0 -0
  18. {txt2stix-0.0.4 → txt2stix-1.0.1}/.github/workflows/create-release.yml +0 -0
  19. {txt2stix-0.0.4 → txt2stix-1.0.1}/.github/workflows/run-tests.yml +0 -0
  20. {txt2stix-0.0.4 → txt2stix-1.0.1}/.gitignore +0 -0
  21. {txt2stix-0.0.4 → txt2stix-1.0.1}/LICENSE +0 -0
  22. {txt2stix-0.0.4 → txt2stix-1.0.1}/README.md +0 -0
  23. {txt2stix-0.0.4 → txt2stix-1.0.1}/docs/README.md +0 -0
  24. {txt2stix-0.0.4 → txt2stix-1.0.1}/docs/stix-mapping.md +0 -0
  25. {txt2stix-0.0.4 → txt2stix-1.0.1}/docs/txt2stix.png +0 -0
  26. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/__init__.py +0 -0
  27. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/extractions/ai/config.yaml +0 -0
  28. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/extractions/lookup/config.yaml +0 -0
  29. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/extractions/pattern/config.yaml +0 -0
  30. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/helpers/mimetype_filename_extension_list.csv +0 -0
  31. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/helpers/stix_relationship_types.txt +0 -0
  32. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/helpers/tlds.txt +0 -0
  33. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/helpers/windows_registry_key_prefix.txt +0 -0
  34. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/_README.md +0 -0
  35. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/_generate_lookups.py +0 -0
  36. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/attack_pattern.txt +0 -0
  37. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/campaign.txt +0 -0
  38. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/country_iso3166_alpha2.txt +0 -0
  39. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/course_of_action.txt +0 -0
  40. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/disarm_id_v1_5.txt +0 -0
  41. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/disarm_name_v1_5.txt +0 -0
  42. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/extensions.txt +0 -0
  43. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/identity.txt +0 -0
  44. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/infrastructure.txt +0 -0
  45. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/intrusion_set.txt +0 -0
  46. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/malware.txt +0 -0
  47. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_atlas_id_v4_5_2.txt +0 -0
  48. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_atlas_name_v4_5_2.txt +0 -0
  49. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_attack_enterprise_aliases_v16_0.txt +0 -0
  50. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_attack_enterprise_id_v16_0.txt +0 -0
  51. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_attack_enterprise_name_v16_0.txt +0 -0
  52. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_attack_ics_aliases_v16_0.txt +0 -0
  53. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_attack_ics_id_v16_0.txt +0 -0
  54. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_attack_ics_name_v16_0.txt +0 -0
  55. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_attack_mobile_aliases_v16_0.txt +0 -0
  56. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_attack_mobile_id_v16_0.txt +0 -0
  57. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_attack_mobile_name_v16_0.txt +0 -0
  58. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_capec_id_v3_9.txt +0 -0
  59. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_capec_name_v3_9.txt +0 -0
  60. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_cwe_id_v4_15.txt +0 -0
  61. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/mitre_cwe_name_v4_15.txt +0 -0
  62. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/threat_actor.txt +0 -0
  63. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/tld.txt +0 -0
  64. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/lookups/tool.txt +0 -0
  65. {txt2stix-0.0.4 → txt2stix-1.0.1}/includes/tests/test_cases.yaml +0 -0
  66. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/README.md +0 -0
  67. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/ai_country.txt +0 -0
  68. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/ai_mitre_attack_enterprise.txt +0 -0
  69. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/ai_mitre_attack_ics.txt +0 -0
  70. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/ai_mitre_attack_mobile.txt +0 -0
  71. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/ai_mitre_capec.txt +0 -0
  72. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/ai_mitre_cwe.txt +0 -0
  73. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/all_cases.txt +0 -0
  74. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_autonomous_system_number.txt +0 -0
  75. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_bank_card_all.txt +0 -0
  76. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_bank_card_amex.txt +0 -0
  77. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_bank_card_diners.txt +0 -0
  78. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_bank_card_discover.txt +0 -0
  79. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_bank_card_jcb.txt +0 -0
  80. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_bank_card_mastercard.txt +0 -0
  81. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_bank_card_union_pay.txt +0 -0
  82. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_bank_card_visa.txt +0 -0
  83. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_country_alpha2.txt +0 -0
  84. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_cpe_uri.txt +0 -0
  85. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_cryptocurrency_btc_transaction.txt +0 -0
  86. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_cryptocurrency_btc_wallet.txt +0 -0
  87. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_cryptocurrency_eth_transaction.txt +0 -0
  88. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_cryptocurrency_eth_wallet.txt +0 -0
  89. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_cryptocurrency_xmr_transaction.txt +0 -0
  90. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_cryptocurrency_xmr_wallet.txt +0 -0
  91. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_cve_id.txt +0 -0
  92. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_directory_unix.txt +0 -0
  93. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_directory_unix_file.txt +0 -0
  94. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_directory_windows.txt +0 -0
  95. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_directory_windows_with_file.txt +0 -0
  96. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_disarm.txt +0 -0
  97. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_disarm_name.txt +0 -0
  98. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_domain_name_only.txt +0 -0
  99. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_domain_name_subdomain.txt +0 -0
  100. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_email_address.txt +0 -0
  101. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_file_hash_md5.txt +0 -0
  102. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_file_hash_sha_1.txt +0 -0
  103. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_file_hash_sha_224.txt +0 -0
  104. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_file_hash_sha_256.txt +0 -0
  105. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_file_hash_sha_384.txt +0 -0
  106. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_file_hash_sha_512.txt +0 -0
  107. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_file_name.txt +0 -0
  108. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_host_name.txt +0 -0
  109. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_host_name_file.txt +0 -0
  110. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_host_name_path.txt +0 -0
  111. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_host_name_subdomain.txt +0 -0
  112. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_host_name_url.txt +0 -0
  113. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_iban_number.txt +0 -0
  114. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_ipv4_address_cidr.txt +0 -0
  115. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_ipv4_address_only.txt +0 -0
  116. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_ipv4_address_port.txt +0 -0
  117. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_ipv6_address_cidr.txt +0 -0
  118. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_ipv6_address_only.txt +0 -0
  119. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_ipv6_address_port.txt +0 -0
  120. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mac_address.txt +0 -0
  121. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_atlas.txt +0 -0
  122. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_atlas_name.txt +0 -0
  123. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_attack_enterprise.txt +0 -0
  124. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_attack_enterprise_aliases.txt +0 -0
  125. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_attack_enterprise_name.txt +0 -0
  126. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_attack_ics.txt +0 -0
  127. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_attack_ics_aliases.txt +0 -0
  128. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_attack_ics_name.txt +0 -0
  129. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_attack_mobile.txt +0 -0
  130. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_attack_mobile_aliases.txt +0 -0
  131. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_attack_mobile_name.txt +0 -0
  132. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_capec.txt +0 -0
  133. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_capec_name.txt +0 -0
  134. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_cwe.txt +0 -0
  135. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_mitre_cwe_name.txt +0 -0
  136. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_phone_number.txt +0 -0
  137. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_url.txt +0 -0
  138. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_url_file.txt +0 -0
  139. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_url_path.txt +0 -0
  140. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_user_agent.txt +0 -0
  141. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/generic_windows_registry_key.txt +0 -0
  142. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/lookup_attack_pattern.txt +0 -0
  143. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/lookup_campaign.txt +0 -0
  144. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/lookup_course_of_action.txt +0 -0
  145. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/lookup_identity.txt +0 -0
  146. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/lookup_infrastructure.txt +0 -0
  147. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/lookup_intrusion_set.txt +0 -0
  148. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/lookup_malware.txt +0 -0
  149. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/lookup_threat_actor.txt +0 -0
  150. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/extraction_types/lookup_tool.txt +0 -0
  151. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/attack_flow_demo.txt +0 -0
  152. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/basic_relationship.txt +0 -0
  153. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/char_length_too_long.txt +0 -0
  154. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/descriptive_for_ai_relationships_1.txt +0 -0
  155. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/disarm_demo.txt +0 -0
  156. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/embedded_img_ignore.txt +0 -0
  157. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/embedded_link_ignore.txt +0 -0
  158. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/ip1.txt +0 -0
  159. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/ip2.txt +0 -0
  160. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/known_whitelist_match.txt +0 -0
  161. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/mitre_attack_enterprise_ai_demo.txt +0 -0
  162. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/mitre_attack_enterprise_lookup_demo.txt +0 -0
  163. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/mixed_extractions.txt +0 -0
  164. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/test_ai_hash_error_with_stix2_lib.txt +0 -0
  165. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/test_aliases.txt +0 -0
  166. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/test_extraction_boundary.txt +0 -0
  167. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/manually_generated_reports/test_extraction_escapes.txt +0 -0
  168. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/real_intel_reports/APT28-Center-of-Storm-2017.txt +0 -0
  169. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/real_intel_reports/Bitdefender-Labs-Report-X-creat6958-en-EN.txt +0 -0
  170. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/real_intel_reports/FireEyeAPT39.txt +0 -0
  171. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/real_intel_reports/France_CERT_APT31_Pakdoor_TLPWHITE.txt +0 -0
  172. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/real_intel_reports/Group-IB_Ransomware_Uncovered_whitepaper_eng.txt +0 -0
  173. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/real_intel_reports/JOINT_CSA_HUNTING_RU_INTEL_SNAKE_MALWARE_20230509.txt +0 -0
  174. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/real_intel_reports/TA22-0126-QAKBOT-analysis-TLP-GREEN.txt +0 -0
  175. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/real_intel_reports/dinners_card.txt +0 -0
  176. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/real_intel_reports/mandiant-apt1.txt +0 -0
  177. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/data/real_intel_reports/mykings_report_final.txt +0 -0
  178. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/manual-tests/cases-ai-relationships.md +0 -0
  179. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/manual-tests/cases-extraction-type-ai.md +0 -0
  180. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/manual-tests/cases-extraction-type-lookup.md +0 -0
  181. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/manual-tests/cases-extraction-type-pattern.md +0 -0
  182. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/manual-tests/cases-standard-tests.md +0 -0
  183. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/scripts/generate_simple_extraction_test_cases_txt_files.py +0 -0
  184. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/src/__init__.py +0 -0
  185. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/src/test_attack_flow.py +0 -0
  186. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/src/test_extractors.py +0 -0
  187. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/src/test_indicator.py +0 -0
  188. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/src/test_lookups.py +0 -0
  189. {txt2stix-0.0.4 → txt2stix-1.0.1}/tests/src/utils.py +0 -0
  190. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/__init__.py +0 -0
  191. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/ai_extractor/__init__.py +0 -0
  192. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/ai_extractor/anthropic.py +0 -0
  193. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/ai_extractor/deepseek.py +0 -0
  194. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/ai_extractor/gemini.py +0 -0
  195. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/ai_extractor/openai.py +0 -0
  196. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/ai_extractor/openrouter.py +0 -0
  197. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/attack_flow.py +0 -0
  198. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/common.py +0 -0
  199. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/extractions.py +0 -0
  200. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/indicator.py +0 -0
  201. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/lookups.py +0 -0
  202. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/__init__.py +0 -0
  203. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/__init__.py +0 -0
  204. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/base_extractor.py +0 -0
  205. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/card/README.md +0 -0
  206. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/card/__init__.py +0 -0
  207. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/card/amex_card_extractor.py +0 -0
  208. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/card/diners_card_extractor.py +0 -0
  209. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/card/discover_card_extractor.py +0 -0
  210. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/card/jcb_card_extractor.py +0 -0
  211. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/card/master_card_extractor.py +0 -0
  212. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/card/union_card_extractor.py +0 -0
  213. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/card/visa_card_extractor.py +0 -0
  214. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/crypto/__init__.py +0 -0
  215. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/crypto/btc_extractor.py +0 -0
  216. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/directory/__init__.py +0 -0
  217. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/directory/unix_directory_extractor.py +0 -0
  218. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/directory/unix_file_path_extractor.py +0 -0
  219. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/directory/windows_directory_path_extractor.py +0 -0
  220. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/directory/windows_file_path_extractor.py +0 -0
  221. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/domain/__init__.py +0 -0
  222. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/domain/domain_extractor.py +0 -0
  223. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/domain/hostname_extractor.py +0 -0
  224. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/domain/sub_domain_extractor.py +0 -0
  225. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/hashes/__init__.py +0 -0
  226. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/hashes/md5_extractor.py +0 -0
  227. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/hashes/sha1_extractor.py +0 -0
  228. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/hashes/sha224_extractor.py +0 -0
  229. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/hashes/sha2_256_exactor.py +0 -0
  230. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/hashes/sha2_512_exactor.py +0 -0
  231. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/hashes/sha3_256_exactor.py +0 -0
  232. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/hashes/sha3_512_exactor.py +0 -0
  233. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/helper.py +0 -0
  234. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/ip/__init__.py +0 -0
  235. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/ip/ipv4_cidr_extractor.py +0 -0
  236. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/ip/ipv4_extractor.py +0 -0
  237. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/ip/ipv4_port_extractor.py +0 -0
  238. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/ip/ipv6_cidr_extractor.py +0 -0
  239. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/ip/ipv6_extractor.py +0 -0
  240. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/ip/ipv6_port_extractor.py +0 -0
  241. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/others/__init__.py +0 -0
  242. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/others/asn_extractor.py +0 -0
  243. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/others/cpe_extractor.py +0 -0
  244. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/others/cve_extractor.py +0 -0
  245. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/others/email_extractor.py +0 -0
  246. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/others/filename_extractor.py +0 -0
  247. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/others/iban_extractor.py +0 -0
  248. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/others/mac_address_extractor.py +0 -0
  249. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/others/phonenumber_extractor.py +0 -0
  250. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/others/user_agent_extractor.py +0 -0
  251. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/others/windows_registry_key_extractor.py +0 -0
  252. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/url/__init__.py +0 -0
  253. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/url/url_extractor.py +0 -0
  254. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/url/url_file_extractor.py +0 -0
  255. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/pattern/extractors/url/url_path_extractor.py +0 -0
  256. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/retriever.py +0 -0
  257. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix/stix.py +0 -0
  258. {txt2stix-0.0.4 → txt2stix-1.0.1}/txt2stix.py +0 -0
@@ -1,10 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: txt2stix
3
- Version: 0.0.4
3
+ Version: 1.0.1
4
4
  Summary: txt2stix is a Python script that is designed to identify and extract IoCs and TTPs from text files, identify the relationships between them, convert them to STIX 2.1 objects, and output as a STIX 2.1 bundle.
5
5
  Project-URL: Homepage, https://github.com/muchdogesec/txt2stix
6
6
  Project-URL: Issues, https://github.com/muchdogesec/txt2stix/issues
7
- Author-email: DOGESEC <support@dogesec.com>
7
+ Project-URL: dogesec HQ, https://dogesec.com
8
+ Author: dogesec
9
+ Maintainer: dogesec
8
10
  License-File: LICENSE
9
11
  Classifier: License :: OSI Approved :: Apache Software License
10
12
  Classifier: Operating System :: OS Independent
@@ -16,7 +18,6 @@ Requires-Dist: llama-index-core>=0.12.42
16
18
  Requires-Dist: llama-index-llms-anthropic>=0.7.2
17
19
  Requires-Dist: llama-index-llms-deepseek>=0.1.2
18
20
  Requires-Dist: llama-index-llms-gemini>=0.5.0
19
- Requires-Dist: llama-index-llms-openai-like>=0.4.0
20
21
  Requires-Dist: llama-index-llms-openai>=0.4.5
21
22
  Requires-Dist: llama-index-llms-openrouter>=0.3.2
22
23
  Requires-Dist: mistune>=3.0.2
@@ -4,8 +4,13 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "txt2stix"
7
- version = "0.0.4"
8
- authors = [{ name = "DOGESEC", email = "support@dogesec.com" }]
7
+ version = "1.0.1"
8
+ authors = [
9
+ { name = "dogesec" }
10
+ ]
11
+ maintainers = [
12
+ { name = "dogesec" }
13
+ ]
9
14
  description = "txt2stix is a Python script that is designed to identify and extract IoCs and TTPs from text files, identify the relationships between them, convert them to STIX 2.1 objects, and output as a STIX 2.1 bundle."
10
15
  readme = "README.md"
11
16
  requires-python = ">=3.9"
@@ -32,7 +37,6 @@ dependencies = [
32
37
  'llama-index-llms-anthropic>=0.7.2',
33
38
  'llama-index-llms-gemini>=0.5.0',
34
39
  'llama-index-llms-openai>=0.4.5',
35
- 'llama-index-llms-openai-like>=0.4.0',
36
40
  'llama-index-llms-deepseek>=0.1.2',
37
41
  'llama-index-llms-openrouter>=0.3.2',
38
42
  'mistune>=3.0.2',
@@ -46,7 +50,7 @@ allow-direct-references = true
46
50
  [project.urls]
47
51
  Homepage = "https://github.com/muchdogesec/txt2stix"
48
52
  Issues = "https://github.com/muchdogesec/txt2stix/issues"
49
-
53
+ "dogesec HQ" = "https://dogesec.com"
50
54
 
51
55
  [project.scripts]
52
56
  stix2arango = "txt2stix.txt2stix:main"
@@ -6,15 +6,15 @@
6
6
  #
7
7
  aiohappyeyeballs==2.6.1
8
8
  # via aiohttp
9
- aiohttp==3.12.12
9
+ aiohttp==3.12.13
10
10
  # via llama-index-core
11
- aiosignal==1.3.2
11
+ aiosignal==1.4.0
12
12
  # via aiohttp
13
13
  aiosqlite==0.21.0
14
14
  # via llama-index-core
15
15
  annotated-types==0.7.0
16
16
  # via pydantic
17
- anthropic[bedrock,vertex]==0.54.0
17
+ anthropic[bedrock,vertex]==0.57.1
18
18
  # via llama-index-llms-anthropic
19
19
  antlr4-python3-runtime==4.9.3
20
20
  # via stix2-patterns
@@ -25,22 +25,22 @@ anyio==4.9.0
25
25
  # openai
26
26
  attrs==25.3.0
27
27
  # via aiohttp
28
- banks==2.1.2
28
+ banks==2.1.3
29
29
  # via llama-index-core
30
30
  base58==2.1.1
31
31
  # via txt2stix (pyproject.toml)
32
32
  beautifulsoup4==4.13.4
33
33
  # via txt2stix (pyproject.toml)
34
- boto3==1.38.35
34
+ boto3==1.39.3
35
35
  # via anthropic
36
- botocore==1.38.35
36
+ botocore==1.39.3
37
37
  # via
38
38
  # anthropic
39
39
  # boto3
40
40
  # s3transfer
41
41
  cachetools==5.5.2
42
42
  # via google-auth
43
- certifi==2025.4.26
43
+ certifi==2025.6.15
44
44
  # via
45
45
  # httpcore
46
46
  # httpx
@@ -57,6 +57,7 @@ deprecated==1.2.18
57
57
  # via
58
58
  # banks
59
59
  # llama-index-core
60
+ # llama-index-instrumentation
60
61
  dirtyjson==1.0.8
61
62
  # via llama-index-core
62
63
  distro==1.9.0
@@ -80,12 +81,12 @@ fsspec==2025.5.1
80
81
  # llama-index-core
81
82
  google-ai-generativelanguage==0.6.15
82
83
  # via google-generativeai
83
- google-api-core[grpc]==2.25.0
84
+ google-api-core[grpc]==2.25.1
84
85
  # via
85
86
  # google-ai-generativelanguage
86
87
  # google-api-python-client
87
88
  # google-generativeai
88
- google-api-python-client==2.172.0
89
+ google-api-python-client==2.175.0
89
90
  # via google-generativeai
90
91
  google-auth[requests]==2.40.3
91
92
  # via
@@ -107,15 +108,15 @@ greenlet==3.2.3
107
108
  # via sqlalchemy
108
109
  griffe==1.7.3
109
110
  # via banks
110
- grpcio==1.73.0
111
+ grpcio==1.73.1
111
112
  # via
112
113
  # google-api-core
113
114
  # grpcio-status
114
- grpcio-status==1.71.0
115
+ grpcio-status==1.71.2
115
116
  # via google-api-core
116
117
  h11==0.16.0
117
118
  # via httpcore
118
- hf-xet==1.1.3
119
+ hf-xet==1.1.5
119
120
  # via huggingface-hub
120
121
  httpcore==1.0.9
121
122
  # via httpx
@@ -128,7 +129,7 @@ httpx==0.28.1
128
129
  # anthropic
129
130
  # llama-index-core
130
131
  # openai
131
- huggingface-hub==0.33.0
132
+ huggingface-hub==0.33.2
132
133
  # via
133
134
  # tokenizers
134
135
  # transformers
@@ -151,7 +152,7 @@ jmespath==1.0.1
151
152
  # botocore
152
153
  joblib==1.5.1
153
154
  # via nltk
154
- llama-index-core==0.12.42
155
+ llama-index-core==0.12.47
155
156
  # via
156
157
  # llama-index-llms-anthropic
157
158
  # llama-index-llms-gemini
@@ -159,13 +160,15 @@ llama-index-core==0.12.42
159
160
  # llama-index-llms-openai-like
160
161
  # llama-index-llms-openrouter
161
162
  # txt2stix (pyproject.toml)
162
- llama-index-llms-anthropic==0.7.2
163
+ llama-index-instrumentation==0.2.0
164
+ # via llama-index-workflows
165
+ llama-index-llms-anthropic==0.7.6
163
166
  # via txt2stix (pyproject.toml)
164
167
  llama-index-llms-deepseek==0.1.2
165
168
  # via txt2stix (pyproject.toml)
166
169
  llama-index-llms-gemini==0.5.0
167
170
  # via txt2stix (pyproject.toml)
168
- llama-index-llms-openai==0.4.5
171
+ llama-index-llms-openai==0.4.7
169
172
  # via
170
173
  # llama-index-llms-openai-like
171
174
  # txt2stix (pyproject.toml)
@@ -173,16 +176,17 @@ llama-index-llms-openai-like==0.4.0
173
176
  # via
174
177
  # llama-index-llms-deepseek
175
178
  # llama-index-llms-openrouter
176
- # txt2stix (pyproject.toml)
177
179
  llama-index-llms-openrouter==0.3.2
178
180
  # via txt2stix (pyproject.toml)
181
+ llama-index-workflows==1.0.1
182
+ # via llama-index-core
179
183
  markupsafe==3.0.2
180
184
  # via jinja2
181
185
  marshmallow==3.26.1
182
186
  # via dataclasses-json
183
187
  mistune==3.1.3
184
188
  # via txt2stix (pyproject.toml)
185
- multidict==6.4.4
189
+ multidict==6.6.3
186
190
  # via
187
191
  # aiohttp
188
192
  # yarl
@@ -194,20 +198,20 @@ networkx==3.5
194
198
  # via llama-index-core
195
199
  nltk==3.9.1
196
200
  # via llama-index-core
197
- numpy==2.3.0
201
+ numpy==2.3.1
198
202
  # via
199
203
  # llama-index-core
200
204
  # transformers
201
- openai==1.86.0
205
+ openai==1.93.2
202
206
  # via llama-index-llms-openai
203
207
  packaging==25.0
204
208
  # via
205
209
  # huggingface-hub
206
210
  # marshmallow
207
211
  # transformers
208
- pathvalidate==3.2.3
212
+ pathvalidate==3.3.1
209
213
  # via txt2stix (pyproject.toml)
210
- phonenumbers==9.0.7
214
+ phonenumbers==9.0.9
211
215
  # via txt2stix (pyproject.toml)
212
216
  pillow==10.4.0
213
217
  # via
@@ -239,12 +243,14 @@ pyasn1-modules==0.4.2
239
243
  # via google-auth
240
244
  pycountry==24.6.1
241
245
  # via schwifty
242
- pydantic==2.11.5
246
+ pydantic==2.11.7
243
247
  # via
244
248
  # anthropic
245
249
  # banks
246
250
  # google-generativeai
247
251
  # llama-index-core
252
+ # llama-index-instrumentation
253
+ # llama-index-workflows
248
254
  # openai
249
255
  pydantic-core==2.33.2
250
256
  # via pydantic
@@ -252,7 +258,7 @@ pyparsing==3.2.3
252
258
  # via httplib2
253
259
  python-dateutil==2.9.0.post0
254
260
  # via botocore
255
- python-dotenv==1.1.0
261
+ python-dotenv==1.1.1
256
262
  # via txt2stix (pyproject.toml)
257
263
  pytz==2025.2
258
264
  # via stix2
@@ -289,7 +295,7 @@ s3transfer==0.13.0
289
295
  # via boto3
290
296
  safetensors==0.5.3
291
297
  # via transformers
292
- schwifty==2025.1.0
298
+ schwifty==2025.6.0
293
299
  # via txt2stix (pyproject.toml)
294
300
  simplejson==3.20.1
295
301
  # via stix2
@@ -310,7 +316,7 @@ stix2==3.0.1
310
316
  # via stix2extensions
311
317
  stix2-patterns==2.0.0
312
318
  # via stix2
313
- stix2extensions @ https://github.com/muchdogesec/stix2extensions/releases/download/main-2025-05-19-15-30-06/stix2extensions-0.0.3-py3-none-any.whl
319
+ stix2extensions==1.0.0
314
320
  # via txt2stix (pyproject.toml)
315
321
  tenacity==9.1.2
316
322
  # via llama-index-core
@@ -320,7 +326,7 @@ tld==0.13.1
320
326
  # via txt2stix (pyproject.toml)
321
327
  tldextract==5.3.0
322
328
  # via txt2stix (pyproject.toml)
323
- tokenizers==0.21.1
329
+ tokenizers==0.21.2
324
330
  # via transformers
325
331
  tqdm==4.67.1
326
332
  # via
@@ -330,9 +336,9 @@ tqdm==4.67.1
330
336
  # nltk
331
337
  # openai
332
338
  # transformers
333
- transformers==4.52.4
339
+ transformers==4.53.1
334
340
  # via llama-index-llms-openai-like
335
- typing-extensions==4.14.0
341
+ typing-extensions==4.14.1
336
342
  # via
337
343
  # aiosqlite
338
344
  # anthropic
@@ -366,3 +372,6 @@ wrapt==1.17.2
366
372
  # llama-index-core
367
373
  yarl==1.20.1
368
374
  # via aiohttp
375
+
376
+ # The following packages are considered to be unsafe in a requirements file:
377
+ # setuptools
@@ -0,0 +1,297 @@
1
+ from unittest.mock import MagicMock, call, patch
2
+ import uuid
3
+
4
+ import pytest
5
+ from txt2stix.bundler import txt2stixBundler, TLP_LEVEL
6
+ from txt2stix.common import MinorException
7
+ from . import utils
8
+ from dateutil.parser import parse as parse_date
9
+ from stix2 import Identity, Relationship
10
+ from stix2extensions import Weakness, BankCard
11
+
12
+ dummy_identity = Identity(
13
+ **{
14
+ "type": "identity",
15
+ "spec_version": "2.1",
16
+ "id": "identity--b1ae1a15-abcd-431e-b990-1b9678f35e15",
17
+ "name": "Test Identity",
18
+ }
19
+ )
20
+
21
+
22
+ @pytest.mark.parametrize(
23
+ ["tlp_level", "identity", "created", "modified"],
24
+ [
25
+ ("red", None, None, "2024-01-01T16:00:00.000Z"),
26
+ ("green", None, "2024-10-09T16:00:00.000Z", None),
27
+ ("amber", dummy_identity, None, "2024-01-01T16:00:00.000Z"),
28
+ ("clear", None, "2024-10-09T16:00:00.000Z", "2024-01-01T16:00:00.000Z"),
29
+ ],
30
+ )
31
+ def test_constructor(tlp_level, identity, created, modified):
32
+ report_id = str(uuid.uuid4())
33
+ bundler = txt2stixBundler(
34
+ "n",
35
+ identity,
36
+ tlp_level,
37
+ "",
38
+ 0,
39
+ [],
40
+ [],
41
+ report_id,
42
+ created=created,
43
+ modified=modified,
44
+ )
45
+ assert bundler.tlp_level.name == tlp_level
46
+ assert bundler.report.id == "report--" + report_id
47
+ assert bundler.tlp_level.value["id"] in bundler.report.object_marking_refs
48
+ assert bundler.report.published == bundler.report.created
49
+ if identity:
50
+ assert identity == bundler.identity, "passed identity ignored"
51
+ else:
52
+ assert (
53
+ bundler.identity == bundler.default_identity
54
+ ), "default identity must be used if no identity is passed"
55
+ assert (
56
+ bundler.report.created_by_ref == bundler.identity["id"]
57
+ ), "report not using bundler.identity"
58
+ if not modified:
59
+ assert (
60
+ bundler.report.modified == bundler.report.created
61
+ ), "modified and created should be the same if modified is not passed"
62
+ else:
63
+ assert bundler.report.modified == parse_date(modified)
64
+ if created:
65
+ assert bundler.report.created == parse_date(created)
66
+
67
+ assert (
68
+ bundler.identity in bundler.bundle.objects
69
+ ), "identity must be in bundle.objects"
70
+ assert (
71
+ bundler.tlp_level.value in bundler.bundle.objects
72
+ ), "tlp_level marking definition must be in bundle.objects"
73
+ assert bundler.report in bundler.bundle.objects, "report must be in bundle.objects"
74
+
75
+
76
+ @pytest.mark.parametrize(
77
+ "obj",
78
+ [
79
+ Weakness(name="test weakness"),
80
+ BankCard(number="1234567891011"),
81
+ ],
82
+ )
83
+ def test_add_ref(obj):
84
+ bundler = utils.dummy_bundler()
85
+ bundler.add_ref(obj)
86
+ assert obj in bundler.bundle.objects
87
+ assert obj.id in bundler.added_objects
88
+
89
+
90
+ def test_add_indicator():
91
+ bundler = utils.dummy_bundler()
92
+ mocked_extractor = MagicMock()
93
+ bundler.all_extractors = dict(placeholder_extractor=mocked_extractor)
94
+ mocked_related_refs = MagicMock()
95
+ mocked_observables = MagicMock()
96
+ with patch.object(txt2stixBundler, 'new_indicator') as mock_new_indicator, patch(
97
+ "txt2stix.bundler.build_observables"
98
+ ) as mock_build_observables:
99
+ extracted_dict = dict(type='placeholder_extractor', value='test value', id='extract-19')
100
+ mock_build_observables.return_value = mocked_observables, mocked_related_refs
101
+ bundler.add_indicator(extracted_dict, True)
102
+
103
+
104
+ mock_new_indicator.assert_called_once_with(mocked_extractor, mocked_extractor.stix_mapping, extracted_dict['value'])
105
+ mock_build_observables.assert_called_once_with(bundler, mocked_extractor.stix_mapping, mock_new_indicator.return_value, extracted_dict['value'], mocked_extractor)
106
+ assert bundler.id_map[extracted_dict["id"]] == mocked_related_refs
107
+
108
+
109
+ def test_add_indicator_sets_id_map():
110
+ extractor = MagicMock()
111
+ extractor.stix_mapping = "domain-name"
112
+ extractor.slug = "testslug"
113
+ extractor.version = "1.0"
114
+
115
+ bundler = txt2stixBundler(
116
+ name="Test",
117
+ identity=None,
118
+ tlp_level="red",
119
+ description="desc",
120
+ confidence=20,
121
+ extractors={"domain": extractor},
122
+ labels=[]
123
+ )
124
+
125
+ # patch build_observables to return one object
126
+ with patch("txt2stix.bundler.build_observables") as mock_build:
127
+ mock_build.return_value = ([{"type": "domain-name", "id": "domain-name--926a1335-a4d7-40d3-804c-3aa53da6fc9e", "value": "test.com"}], ["domain-name--926a1335-a4d7-40d3-804c-3aa53da6fc9e"])
128
+
129
+ extracted = {"type": "domain", "value": "test.com", "id": "testid"}
130
+ bundler.add_indicator(extracted, add_standard_relationship=False)
131
+
132
+ assert "testid" in bundler.id_map
133
+ assert bundler.id_map["testid"] == ["domain-name--926a1335-a4d7-40d3-804c-3aa53da6fc9e"]
134
+ assert "domain-name--926a1335-a4d7-40d3-804c-3aa53da6fc9e" in bundler.id_value_map
135
+
136
+ def test_add_indicator_raises_minor_exception():
137
+ extractor = MagicMock()
138
+ extractor.stix_mapping = "domain-name"
139
+ extractor.slug = "testslug"
140
+ extractor.version = "1.0"
141
+
142
+ bundler = txt2stixBundler(
143
+ name="Test",
144
+ identity=None,
145
+ tlp_level="red",
146
+ description="desc",
147
+ confidence=20,
148
+ extractors={"domain": extractor},
149
+ labels=[]
150
+ )
151
+
152
+ # patch build_observables to return one object
153
+ with patch("txt2stix.bundler.build_observables") as mock_build, pytest.raises(MinorException):
154
+ mock_build.return_value = ([], [])
155
+
156
+ extracted = {"type": "domain", "value": "test.com", "id": "testid"}
157
+ bundler.add_indicator(extracted, add_standard_relationship=False)
158
+
159
+
160
+
161
+ def test_flow_objects():
162
+ bundler = txt2stixBundler(
163
+ name="FlowTest",
164
+ identity=None,
165
+ tlp_level="clear",
166
+ description="desc",
167
+ confidence=10,
168
+ extractors={},
169
+ labels=[]
170
+ )
171
+
172
+ obj = {"id": "indicator--123", "type": "indicator", "name": "x"}
173
+ bundler.flow_objects = [obj, bundler.report]
174
+
175
+ assert "indicator--123" in bundler.id_value_map
176
+ assert obj in bundler.bundle.objects
177
+ assert bundler.flow_objects == [obj, bundler.report]
178
+
179
+
180
+
181
+
182
+ def test_add_standard_relationship():
183
+ bundler = txt2stixBundler(
184
+ name="Test",
185
+ identity=None,
186
+ tlp_level="amber",
187
+ description="desc",
188
+ confidence=30,
189
+ extractors={},
190
+ labels=[],
191
+ report_id="d9f3b306-e7fe-4074-b89a-33ce54280718"
192
+ )
193
+
194
+ bundler.id_value_map["identity--6493ad42-ec4d-4260-b2e9-3f3a1110193c"] = "valA"
195
+ bundler.id_value_map["phone-number--8764871f-6521-4401-bbf2-a17538435f49"] = "valB"
196
+
197
+ bundler.add_standard_relationship("identity--6493ad42-ec4d-4260-b2e9-3f3a1110193c", "phone-number--8764871f-6521-4401-bbf2-a17538435f49", "xx-related-to")
198
+ assert "relationship--290e1319-7a95-5f51-b2c5-463f896cb35a" in bundler.added_objects
199
+
200
+
201
+ found = [obj for obj in bundler.bundle.objects if obj['id'] == "relationship--290e1319-7a95-5f51-b2c5-463f896cb35a"][0]
202
+ assert found.description == "valA xx related to valB"
203
+ assert found.relationship_type == "xx-related-to"
204
+ assert found.source_ref == "identity--6493ad42-ec4d-4260-b2e9-3f3a1110193c"
205
+ assert found.target_ref == "phone-number--8764871f-6521-4401-bbf2-a17538435f49"
206
+
207
+ def test_add_ai_relationship():
208
+ bundler = txt2stixBundler(
209
+ name="Test",
210
+ identity=None,
211
+ tlp_level="amber",
212
+ description="desc",
213
+ confidence=30,
214
+ extractors={},
215
+ labels=[],
216
+ report_id="d9f3b306-e7fe-4074-b89a-33ce54280718"
217
+ )
218
+ bundler.id_map['ex1'] = ["phone-number--8764871f-6521-4401-bbf2-a17538435f49", "indicator--401855b2-bd7a-444f-95b1-723efbdba33b"]
219
+ bundler.id_map['ex2'] = ["identity--6493ad42-ec4d-4260-b2e9-3f3a1110193c"]
220
+ bundler.id_value_map["identity--6493ad42-ec4d-4260-b2e9-3f3a1110193c"] = "valA"
221
+ bundler.id_value_map["phone-number--8764871f-6521-4401-bbf2-a17538435f49"] = "valB"
222
+
223
+ with patch.object(txt2stixBundler, 'add_standard_relationship') as mock_add_standard_relationship:
224
+ bundler.add_ai_relationship(dict(source_ref='ex1', target_ref='ex2', relationship_type='in-use-by'))
225
+ mock_add_standard_relationship.assert_any_call("phone-number--8764871f-6521-4401-bbf2-a17538435f49", "identity--6493ad42-ec4d-4260-b2e9-3f3a1110193c", "in-use-by")
226
+ mock_add_standard_relationship.assert_any_call("indicator--401855b2-bd7a-444f-95b1-723efbdba33b", "identity--6493ad42-ec4d-4260-b2e9-3f3a1110193c", "in-use-by")
227
+
228
+
229
+
230
+ def test_add_summary():
231
+ bundler = txt2stixBundler(
232
+ name="Test",
233
+ identity=None,
234
+ tlp_level="amber",
235
+ description="desc",
236
+ confidence=30,
237
+ extractors={},
238
+ labels=['report-label1'],
239
+ report_id="d9f3b306-e7fe-4074-b89a-33ce54280718"
240
+ )
241
+ summary = "This is a summary"
242
+ bundler.add_summary(summary, "some-random-ai-provider")
243
+ assert 'note--d9f3b306-e7fe-4074-b89a-33ce54280718' in bundler.added_objects
244
+ assert 'relationship--fc73fe53-9487-540f-bd65-582d9d2d1b54' in bundler.added_objects
245
+ note_obj = [obj for obj in bundler.bundle.objects if obj['id'] == 'note--d9f3b306-e7fe-4074-b89a-33ce54280718'][0]
246
+ assert note_obj.content == summary
247
+ assert note_obj.object_refs == ["report--d9f3b306-e7fe-4074-b89a-33ce54280718"]
248
+ for k in ['created', 'modified', 'created_by_ref', 'object_marking_refs', 'labels', 'confidence']:
249
+ assert bundler.report[k] == note_obj[k]
250
+
251
+ ref_obj = [obj for obj in bundler.bundle.objects if obj['id'] == 'relationship--fc73fe53-9487-540f-bd65-582d9d2d1b54'][0]
252
+ assert ref_obj.description == "AI generated summary for Test"
253
+ assert ref_obj.external_references == note_obj.external_references
254
+
255
+
256
+ def test_process_observables_and_process_relationships():
257
+ extractor = MagicMock()
258
+ extractor.stix_mapping = "domain-name"
259
+ extractor.slug = "testslug"
260
+ extractor.version = "1.0"
261
+
262
+ bundler = txt2stixBundler(
263
+ name="Test Process",
264
+ identity=None,
265
+ tlp_level="amber_strict",
266
+ description="desc",
267
+ confidence=90,
268
+ extractors={"domain": extractor},
269
+ labels=[]
270
+ )
271
+
272
+ with patch("txt2stix.bundler.build_observables") as mock_build:
273
+ mock_build.return_value = ([{"type": "domain-name", "id": "domain-name--5b35eddb-c7fc-43c6-859b-36bb859ebb7c", "value": "foo.com"}], ["domain-name--5b35eddb-c7fc-43c6-859b-36bb859ebb7c"])
274
+ bundler.process_observables([{"type": "domain", "value": "foo.com"}])
275
+
276
+ assert bundler.observables_processed == 1
277
+ assert "domain-name--5b35eddb-c7fc-43c6-859b-36bb859ebb7c" in bundler.id_value_map
278
+
279
+ # test process_relationships
280
+ bundler.id_map = {"ai_src": ["a"], "ai_tgt": ["b"]}
281
+ with patch.object(bundler, "add_standard_relationship") as mock_add_rel:
282
+ bundler.process_relationships([{"source_ref": "ai_src", "target_ref": "ai_tgt", "relationship_type": "controls"}])
283
+ mock_add_rel.assert_called_once_with("a", "b", "controls")
284
+
285
+ def test_tlp_level_values():
286
+ values = TLP_LEVEL.values()
287
+ assert all(v.type == "marking-definition" for v in values)
288
+ assert len(values) == 5
289
+
290
+ def test_tlp_level_get_by_enum():
291
+ assert TLP_LEVEL.get(TLP_LEVEL.CLEAR) == TLP_LEVEL.CLEAR
292
+
293
+ def test_tlp_level_get_by_string():
294
+ assert TLP_LEVEL.get("clear") == TLP_LEVEL.CLEAR
295
+ assert TLP_LEVEL.get("amber_strict") == TLP_LEVEL.AMBER_STRICT
296
+ assert TLP_LEVEL.get("amber+strict") == TLP_LEVEL.AMBER_STRICT
297
+ assert TLP_LEVEL.get("amber-strict") == TLP_LEVEL.AMBER_STRICT