bbot 2.0.1.4720rc0__py3-none-any.whl → 2.3.0.5401rc0__py3-none-any.whl

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 bbot might be problematic. Click here for more details.

Files changed (278) hide show
  1. bbot/__init__.py +1 -1
  2. bbot/cli.py +3 -7
  3. bbot/core/config/files.py +0 -1
  4. bbot/core/config/logger.py +34 -4
  5. bbot/core/core.py +21 -4
  6. bbot/core/engine.py +9 -8
  7. bbot/core/event/base.py +131 -52
  8. bbot/core/helpers/bloom.py +10 -3
  9. bbot/core/helpers/command.py +8 -7
  10. bbot/core/helpers/depsinstaller/installer.py +31 -13
  11. bbot/core/helpers/diff.py +10 -10
  12. bbot/core/helpers/dns/brute.py +7 -4
  13. bbot/core/helpers/dns/dns.py +1 -2
  14. bbot/core/helpers/dns/engine.py +4 -6
  15. bbot/core/helpers/dns/helpers.py +2 -2
  16. bbot/core/helpers/dns/mock.py +0 -1
  17. bbot/core/helpers/files.py +1 -1
  18. bbot/core/helpers/helper.py +7 -4
  19. bbot/core/helpers/interactsh.py +3 -3
  20. bbot/core/helpers/libmagic.py +65 -0
  21. bbot/core/helpers/misc.py +65 -22
  22. bbot/core/helpers/names_generator.py +17 -3
  23. bbot/core/helpers/process.py +0 -20
  24. bbot/core/helpers/regex.py +1 -1
  25. bbot/core/helpers/regexes.py +12 -6
  26. bbot/core/helpers/validators.py +1 -2
  27. bbot/core/helpers/web/client.py +1 -1
  28. bbot/core/helpers/web/engine.py +1 -2
  29. bbot/core/helpers/web/web.py +4 -114
  30. bbot/core/helpers/wordcloud.py +5 -5
  31. bbot/core/modules.py +36 -27
  32. bbot/core/multiprocess.py +58 -0
  33. bbot/core/shared_deps.py +46 -3
  34. bbot/db/sql/models.py +147 -0
  35. bbot/defaults.yml +12 -10
  36. bbot/modules/anubisdb.py +2 -2
  37. bbot/modules/apkpure.py +63 -0
  38. bbot/modules/azure_tenant.py +2 -2
  39. bbot/modules/baddns.py +35 -19
  40. bbot/modules/baddns_direct.py +92 -0
  41. bbot/modules/baddns_zone.py +3 -8
  42. bbot/modules/badsecrets.py +4 -3
  43. bbot/modules/base.py +195 -51
  44. bbot/modules/bevigil.py +7 -7
  45. bbot/modules/binaryedge.py +7 -4
  46. bbot/modules/bufferoverrun.py +47 -0
  47. bbot/modules/builtwith.py +6 -10
  48. bbot/modules/bypass403.py +5 -5
  49. bbot/modules/c99.py +10 -7
  50. bbot/modules/censys.py +9 -13
  51. bbot/modules/certspotter.py +5 -3
  52. bbot/modules/chaos.py +9 -7
  53. bbot/modules/code_repository.py +1 -0
  54. bbot/modules/columbus.py +3 -3
  55. bbot/modules/crt.py +5 -3
  56. bbot/modules/deadly/dastardly.py +1 -1
  57. bbot/modules/deadly/ffuf.py +9 -9
  58. bbot/modules/deadly/nuclei.py +3 -3
  59. bbot/modules/deadly/vhost.py +4 -3
  60. bbot/modules/dehashed.py +1 -1
  61. bbot/modules/digitorus.py +1 -1
  62. bbot/modules/dnsbimi.py +145 -0
  63. bbot/modules/dnscaa.py +3 -3
  64. bbot/modules/dnsdumpster.py +4 -4
  65. bbot/modules/dnstlsrpt.py +144 -0
  66. bbot/modules/docker_pull.py +7 -5
  67. bbot/modules/dockerhub.py +2 -2
  68. bbot/modules/dotnetnuke.py +20 -21
  69. bbot/modules/emailformat.py +1 -1
  70. bbot/modules/extractous.py +122 -0
  71. bbot/modules/filedownload.py +9 -7
  72. bbot/modules/fullhunt.py +7 -4
  73. bbot/modules/generic_ssrf.py +5 -5
  74. bbot/modules/github_codesearch.py +3 -2
  75. bbot/modules/github_org.py +4 -4
  76. bbot/modules/github_workflows.py +4 -4
  77. bbot/modules/gitlab.py +2 -5
  78. bbot/modules/google_playstore.py +93 -0
  79. bbot/modules/gowitness.py +48 -50
  80. bbot/modules/hackertarget.py +5 -3
  81. bbot/modules/host_header.py +5 -5
  82. bbot/modules/httpx.py +1 -4
  83. bbot/modules/hunterio.py +3 -9
  84. bbot/modules/iis_shortnames.py +19 -30
  85. bbot/modules/internal/cloudcheck.py +29 -12
  86. bbot/modules/internal/dnsresolve.py +22 -22
  87. bbot/modules/internal/excavate.py +97 -59
  88. bbot/modules/internal/speculate.py +41 -32
  89. bbot/modules/internetdb.py +4 -2
  90. bbot/modules/ip2location.py +3 -5
  91. bbot/modules/ipneighbor.py +1 -1
  92. bbot/modules/ipstack.py +3 -8
  93. bbot/modules/jadx.py +87 -0
  94. bbot/modules/leakix.py +11 -10
  95. bbot/modules/myssl.py +2 -2
  96. bbot/modules/newsletters.py +2 -2
  97. bbot/modules/otx.py +5 -3
  98. bbot/modules/output/asset_inventory.py +7 -7
  99. bbot/modules/output/base.py +1 -1
  100. bbot/modules/output/csv.py +1 -1
  101. bbot/modules/output/http.py +20 -14
  102. bbot/modules/output/mysql.py +51 -0
  103. bbot/modules/output/neo4j.py +7 -2
  104. bbot/modules/output/postgres.py +49 -0
  105. bbot/modules/output/slack.py +0 -1
  106. bbot/modules/output/sqlite.py +29 -0
  107. bbot/modules/output/stdout.py +2 -2
  108. bbot/modules/output/teams.py +107 -6
  109. bbot/modules/paramminer_headers.py +8 -11
  110. bbot/modules/passivetotal.py +13 -13
  111. bbot/modules/portscan.py +32 -6
  112. bbot/modules/postman.py +50 -126
  113. bbot/modules/postman_download.py +220 -0
  114. bbot/modules/rapiddns.py +3 -8
  115. bbot/modules/report/asn.py +18 -11
  116. bbot/modules/robots.py +3 -3
  117. bbot/modules/securitytrails.py +7 -10
  118. bbot/modules/securitytxt.py +1 -1
  119. bbot/modules/shodan_dns.py +7 -9
  120. bbot/modules/sitedossier.py +1 -1
  121. bbot/modules/skymem.py +2 -2
  122. bbot/modules/social.py +2 -1
  123. bbot/modules/subdomaincenter.py +1 -1
  124. bbot/modules/subdomainradar.py +160 -0
  125. bbot/modules/telerik.py +8 -8
  126. bbot/modules/templates/bucket.py +1 -1
  127. bbot/modules/templates/github.py +22 -14
  128. bbot/modules/templates/postman.py +21 -0
  129. bbot/modules/templates/shodan.py +14 -13
  130. bbot/modules/templates/sql.py +95 -0
  131. bbot/modules/templates/subdomain_enum.py +51 -16
  132. bbot/modules/templates/webhook.py +2 -4
  133. bbot/modules/trickest.py +8 -37
  134. bbot/modules/trufflehog.py +10 -12
  135. bbot/modules/url_manipulation.py +3 -3
  136. bbot/modules/urlscan.py +1 -1
  137. bbot/modules/viewdns.py +1 -1
  138. bbot/modules/virustotal.py +8 -30
  139. bbot/modules/wafw00f.py +1 -1
  140. bbot/modules/wayback.py +1 -1
  141. bbot/modules/wpscan.py +17 -11
  142. bbot/modules/zoomeye.py +11 -6
  143. bbot/presets/baddns-thorough.yml +12 -0
  144. bbot/presets/fast.yml +16 -0
  145. bbot/presets/kitchen-sink.yml +1 -2
  146. bbot/presets/spider.yml +4 -0
  147. bbot/presets/subdomain-enum.yml +7 -7
  148. bbot/presets/web/dotnet-audit.yml +0 -1
  149. bbot/scanner/manager.py +5 -16
  150. bbot/scanner/preset/args.py +46 -26
  151. bbot/scanner/preset/environ.py +7 -2
  152. bbot/scanner/preset/path.py +7 -4
  153. bbot/scanner/preset/preset.py +36 -23
  154. bbot/scanner/scanner.py +172 -62
  155. bbot/scanner/target.py +236 -434
  156. bbot/scripts/docs.py +1 -1
  157. bbot/test/bbot_fixtures.py +13 -3
  158. bbot/test/conftest.py +132 -100
  159. bbot/test/fastapi_test.py +17 -0
  160. bbot/test/owasp_mastg.apk +0 -0
  161. bbot/test/run_tests.sh +4 -4
  162. bbot/test/test.conf +2 -0
  163. bbot/test/test_step_1/test__module__tests.py +0 -1
  164. bbot/test/test_step_1/test_bbot_fastapi.py +79 -0
  165. bbot/test/test_step_1/test_bloom_filter.py +2 -1
  166. bbot/test/test_step_1/test_cli.py +138 -64
  167. bbot/test/test_step_1/test_dns.py +61 -27
  168. bbot/test/test_step_1/test_engine.py +17 -19
  169. bbot/test/test_step_1/test_events.py +183 -30
  170. bbot/test/test_step_1/test_helpers.py +64 -29
  171. bbot/test/test_step_1/test_manager_deduplication.py +1 -1
  172. bbot/test/test_step_1/test_manager_scope_accuracy.py +333 -330
  173. bbot/test/test_step_1/test_modules_basic.py +68 -70
  174. bbot/test/test_step_1/test_presets.py +183 -100
  175. bbot/test/test_step_1/test_python_api.py +7 -2
  176. bbot/test/test_step_1/test_regexes.py +35 -5
  177. bbot/test/test_step_1/test_scan.py +39 -5
  178. bbot/test/test_step_1/test_scope.py +4 -3
  179. bbot/test/test_step_1/test_target.py +242 -145
  180. bbot/test/test_step_1/test_web.py +14 -10
  181. bbot/test/test_step_2/module_tests/base.py +15 -7
  182. bbot/test/test_step_2/module_tests/test_module_anubisdb.py +1 -1
  183. bbot/test/test_step_2/module_tests/test_module_apkpure.py +71 -0
  184. bbot/test/test_step_2/module_tests/test_module_asset_inventory.py +0 -1
  185. bbot/test/test_step_2/module_tests/test_module_azure_realm.py +1 -1
  186. bbot/test/test_step_2/module_tests/test_module_baddns.py +6 -6
  187. bbot/test/test_step_2/module_tests/test_module_baddns_direct.py +62 -0
  188. bbot/test/test_step_2/module_tests/test_module_bevigil.py +29 -2
  189. bbot/test/test_step_2/module_tests/test_module_binaryedge.py +4 -2
  190. bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py +2 -2
  191. bbot/test/test_step_2/module_tests/test_module_bucket_azure.py +1 -1
  192. bbot/test/test_step_2/module_tests/test_module_bufferoverrun.py +35 -0
  193. bbot/test/test_step_2/module_tests/test_module_builtwith.py +2 -2
  194. bbot/test/test_step_2/module_tests/test_module_bypass403.py +1 -1
  195. bbot/test/test_step_2/module_tests/test_module_c99.py +126 -0
  196. bbot/test/test_step_2/module_tests/test_module_censys.py +4 -1
  197. bbot/test/test_step_2/module_tests/test_module_cloudcheck.py +4 -0
  198. bbot/test/test_step_2/module_tests/test_module_code_repository.py +11 -1
  199. bbot/test/test_step_2/module_tests/test_module_columbus.py +1 -1
  200. bbot/test/test_step_2/module_tests/test_module_credshed.py +3 -3
  201. bbot/test/test_step_2/module_tests/test_module_dastardly.py +2 -1
  202. bbot/test/test_step_2/module_tests/test_module_dehashed.py +2 -2
  203. bbot/test/test_step_2/module_tests/test_module_digitorus.py +1 -1
  204. bbot/test/test_step_2/module_tests/test_module_discord.py +1 -1
  205. bbot/test/test_step_2/module_tests/test_module_dnsbimi.py +103 -0
  206. bbot/test/test_step_2/module_tests/test_module_dnsbrute.py +9 -10
  207. bbot/test/test_step_2/module_tests/test_module_dnsbrute_mutations.py +1 -2
  208. bbot/test/test_step_2/module_tests/test_module_dnscommonsrv.py +1 -2
  209. bbot/test/test_step_2/module_tests/test_module_dnsdumpster.py +4 -4
  210. bbot/test/test_step_2/module_tests/test_module_dnstlsrpt.py +64 -0
  211. bbot/test/test_step_2/module_tests/test_module_dotnetnuke.py +0 -8
  212. bbot/test/test_step_2/module_tests/test_module_excavate.py +28 -48
  213. bbot/test/test_step_2/module_tests/test_module_extractous.py +54 -0
  214. bbot/test/test_step_2/module_tests/test_module_ffuf_shortnames.py +1 -1
  215. bbot/test/test_step_2/module_tests/test_module_filedownload.py +14 -14
  216. bbot/test/test_step_2/module_tests/test_module_git_clone.py +2 -2
  217. bbot/test/test_step_2/module_tests/test_module_github_org.py +19 -8
  218. bbot/test/test_step_2/module_tests/test_module_github_workflows.py +1 -1
  219. bbot/test/test_step_2/module_tests/test_module_gitlab.py +9 -4
  220. bbot/test/test_step_2/module_tests/test_module_google_playstore.py +83 -0
  221. bbot/test/test_step_2/module_tests/test_module_gowitness.py +4 -6
  222. bbot/test/test_step_2/module_tests/test_module_host_header.py +1 -1
  223. bbot/test/test_step_2/module_tests/test_module_http.py +4 -4
  224. bbot/test/test_step_2/module_tests/test_module_httpx.py +10 -8
  225. bbot/test/test_step_2/module_tests/test_module_hunterio.py +68 -4
  226. bbot/test/test_step_2/module_tests/test_module_jadx.py +55 -0
  227. bbot/test/test_step_2/module_tests/test_module_json.py +22 -9
  228. bbot/test/test_step_2/module_tests/test_module_leakix.py +7 -3
  229. bbot/test/test_step_2/module_tests/test_module_mysql.py +76 -0
  230. bbot/test/test_step_2/module_tests/test_module_myssl.py +1 -1
  231. bbot/test/test_step_2/module_tests/test_module_neo4j.py +1 -1
  232. bbot/test/test_step_2/module_tests/test_module_newsletters.py +16 -16
  233. bbot/test/test_step_2/module_tests/test_module_ntlm.py +8 -7
  234. bbot/test/test_step_2/module_tests/test_module_oauth.py +1 -1
  235. bbot/test/test_step_2/module_tests/test_module_otx.py +1 -1
  236. bbot/test/test_step_2/module_tests/test_module_paramminer_cookies.py +1 -2
  237. bbot/test/test_step_2/module_tests/test_module_paramminer_getparams.py +0 -6
  238. bbot/test/test_step_2/module_tests/test_module_paramminer_headers.py +2 -9
  239. bbot/test/test_step_2/module_tests/test_module_passivetotal.py +3 -1
  240. bbot/test/test_step_2/module_tests/test_module_pgp.py +2 -2
  241. bbot/test/test_step_2/module_tests/test_module_portscan.py +9 -8
  242. bbot/test/test_step_2/module_tests/test_module_postgres.py +74 -0
  243. bbot/test/test_step_2/module_tests/test_module_postman.py +84 -253
  244. bbot/test/test_step_2/module_tests/test_module_postman_download.py +439 -0
  245. bbot/test/test_step_2/module_tests/test_module_rapiddns.py +93 -1
  246. bbot/test/test_step_2/module_tests/test_module_shodan_dns.py +20 -1
  247. bbot/test/test_step_2/module_tests/test_module_sitedossier.py +2 -2
  248. bbot/test/test_step_2/module_tests/test_module_smuggler.py +14 -14
  249. bbot/test/test_step_2/module_tests/test_module_social.py +11 -1
  250. bbot/test/test_step_2/module_tests/test_module_speculate.py +4 -8
  251. bbot/test/test_step_2/module_tests/test_module_splunk.py +4 -4
  252. bbot/test/test_step_2/module_tests/test_module_sqlite.py +18 -0
  253. bbot/test/test_step_2/module_tests/test_module_sslcert.py +1 -1
  254. bbot/test/test_step_2/module_tests/test_module_stdout.py +5 -3
  255. bbot/test/test_step_2/module_tests/test_module_subdomaincenter.py +1 -1
  256. bbot/test/test_step_2/module_tests/test_module_subdomainradar.py +208 -0
  257. bbot/test/test_step_2/module_tests/test_module_subdomains.py +1 -1
  258. bbot/test/test_step_2/module_tests/test_module_teams.py +8 -6
  259. bbot/test/test_step_2/module_tests/test_module_telerik.py +1 -1
  260. bbot/test/test_step_2/module_tests/test_module_trufflehog.py +317 -14
  261. bbot/test/test_step_2/module_tests/test_module_viewdns.py +1 -1
  262. bbot/test/test_step_2/module_tests/test_module_wayback.py +1 -1
  263. bbot/test/test_step_2/template_tests/test_template_subdomain_enum.py +2 -2
  264. bbot/wordlists/devops_mutations.txt +1 -1
  265. bbot/wordlists/ffuf_shortname_candidates.txt +1 -1
  266. bbot/wordlists/nameservers.txt +1 -1
  267. bbot/wordlists/paramminer_headers.txt +1 -1
  268. bbot/wordlists/paramminer_parameters.txt +1 -1
  269. bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt +1 -1
  270. bbot/wordlists/valid_url_schemes.txt +1 -1
  271. {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/METADATA +48 -18
  272. bbot-2.3.0.5401rc0.dist-info/RECORD +421 -0
  273. {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/WHEEL +1 -1
  274. bbot/modules/unstructured.py +0 -163
  275. bbot/test/test_step_2/module_tests/test_module_unstructured.py +0 -102
  276. bbot-2.0.1.4720rc0.dist-info/RECORD +0 -387
  277. {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/LICENSE +0 -0
  278. {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/entry_points.txt +0 -0
@@ -17,11 +17,11 @@ async def test_cli_scope(monkeypatch, capsys):
17
17
  )
18
18
  result = await cli._main()
19
19
  out, err = capsys.readouterr()
20
- assert result == True
20
+ assert result is True
21
21
  lines = [json.loads(l) for l in out.splitlines()]
22
22
  dns_events = [l for l in lines if l["type"] == "DNS_NAME" and l["data"] == "one.one.one.one"]
23
23
  assert dns_events
24
- assert all([l["scope_distance"] == 0 and "in-scope" in l["tags"] for l in dns_events])
24
+ assert all(l["scope_distance"] == 0 and "in-scope" in l["tags"] for l in dns_events)
25
25
  assert 1 == len(
26
26
  [
27
27
  l
@@ -34,10 +34,10 @@ async def test_cli_scope(monkeypatch, capsys):
34
34
  )
35
35
  ip_events = [l for l in lines if l["type"] == "IP_ADDRESS" and l["data"] == "1.1.1.1"]
36
36
  assert ip_events
37
- assert all([l["scope_distance"] == 1 and "distance-1" in l["tags"] for l in ip_events])
37
+ assert all(l["scope_distance"] == 1 and "distance-1" in l["tags"] for l in ip_events)
38
38
  ip_events = [l for l in lines if l["type"] == "IP_ADDRESS" and l["data"] == "1.0.0.1"]
39
39
  assert ip_events
40
- assert all([l["scope_distance"] == 1 and "distance-1" in l["tags"] for l in ip_events])
40
+ assert all(l["scope_distance"] == 1 and "distance-1" in l["tags"] for l in ip_events)
41
41
 
42
42
  # with whitelist
43
43
  monkeypatch.setattr(
@@ -57,14 +57,14 @@ async def test_cli_scope(monkeypatch, capsys):
57
57
  )
58
58
  result = await cli._main()
59
59
  out, err = capsys.readouterr()
60
- assert result == True
60
+ assert result is True
61
61
  lines = [json.loads(l) for l in out.splitlines()]
62
62
  lines = [l for l in lines if l["type"] != "SCAN"]
63
63
  assert lines
64
- assert not any([l["scope_distance"] == 0 for l in lines])
64
+ assert not any(l["scope_distance"] == 0 for l in lines)
65
65
  dns_events = [l for l in lines if l["type"] == "DNS_NAME" and l["data"] == "one.one.one.one"]
66
66
  assert dns_events
67
- assert all([l["scope_distance"] == 1 and "distance-1" in l["tags"] for l in dns_events])
67
+ assert all(l["scope_distance"] == 1 and "distance-1" in l["tags"] for l in dns_events)
68
68
  assert 1 == len(
69
69
  [
70
70
  l
@@ -77,10 +77,10 @@ async def test_cli_scope(monkeypatch, capsys):
77
77
  )
78
78
  ip_events = [l for l in lines if l["type"] == "IP_ADDRESS" and l["data"] == "1.1.1.1"]
79
79
  assert ip_events
80
- assert all([l["scope_distance"] == 2 and "distance-2" in l["tags"] for l in ip_events])
80
+ assert all(l["scope_distance"] == 2 and "distance-2" in l["tags"] for l in ip_events)
81
81
  ip_events = [l for l in lines if l["type"] == "IP_ADDRESS" and l["data"] == "1.0.0.1"]
82
82
  assert ip_events
83
- assert all([l["scope_distance"] == 2 and "distance-2" in l["tags"] for l in ip_events])
83
+ assert all(l["scope_distance"] == 2 and "distance-2" in l["tags"] for l in ip_events)
84
84
 
85
85
 
86
86
  @pytest.mark.asyncio
@@ -97,7 +97,7 @@ async def test_cli_scan(monkeypatch):
97
97
  ["bbot", "-y", "-t", "127.0.0.1", "www.example.com", "-n", "test_cli_scan", "-c", "dns.disable=true"],
98
98
  )
99
99
  result = await cli._main()
100
- assert result == True
100
+ assert result is True
101
101
 
102
102
  scan_home = scans_home / "test_cli_scan"
103
103
  assert (scan_home / "preset.yml").is_file(), "preset.yml not found"
@@ -139,14 +139,14 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
139
139
  monkeypatch.setattr("sys.argv", ["bbot", "--version"])
140
140
  result = await cli._main()
141
141
  out, err = capsys.readouterr()
142
- assert result == None
142
+ assert result is None
143
143
  assert len(out.splitlines()) == 1
144
144
  assert out.count(".") > 1
145
145
 
146
146
  # list modules
147
147
  monkeypatch.setattr("sys.argv", ["bbot", "--list-modules"])
148
148
  result = await cli._main()
149
- assert result == None
149
+ assert result is None
150
150
  out, err = capsys.readouterr()
151
151
  # internal modules
152
152
  assert "| excavate " in out
@@ -162,7 +162,7 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
162
162
  assert not output_dir.exists()
163
163
  monkeypatch.setattr("sys.argv", ["bbot", "-o", str(output_dir), "-n", scan_name, "-y"])
164
164
  result = await cli._main()
165
- assert result == True
165
+ assert result is True
166
166
  assert output_dir.is_dir()
167
167
  assert scan_dir.is_dir()
168
168
  assert "[SCAN]" in open(scan_dir / "output.txt").read()
@@ -173,7 +173,7 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
173
173
  monkeypatch.setattr("sys.argv", ["bbot", "--list-module-options"])
174
174
  result = await cli._main()
175
175
  out, err = capsys.readouterr()
176
- assert result == None
176
+ assert result is None
177
177
  assert "| modules.wayback.urls" in out
178
178
  assert "| bool" in out
179
179
  assert "| emit URLs in addition to DNS_NAMEs" in out
@@ -185,36 +185,36 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
185
185
  monkeypatch.setattr("sys.argv", ["bbot", "-f", "subdomain-enum", "--list-module-options"])
186
186
  result = await cli._main()
187
187
  out, err = capsys.readouterr()
188
- assert result == None
188
+ assert result is None
189
189
  assert "| modules.wayback.urls" in out
190
190
  assert "| bool" in out
191
191
  assert "| emit URLs in addition to DNS_NAMEs" in out
192
192
  assert "| False" in out
193
193
  assert "| modules.dnsbrute.wordlist" in out
194
- assert not "| modules.robots.include_allow" in out
194
+ assert "| modules.robots.include_allow" not in out
195
195
 
196
196
  # list module options by module
197
197
  monkeypatch.setattr("sys.argv", ["bbot", "-m", "dnsbrute", "-lmo"])
198
198
  result = await cli._main()
199
199
  out, err = capsys.readouterr()
200
- assert result == None
200
+ assert result is None
201
201
  assert out.count("modules.") == out.count("modules.dnsbrute.")
202
- assert not "| modules.wayback.urls" in out
202
+ assert "| modules.wayback.urls" not in out
203
203
  assert "| modules.dnsbrute.wordlist" in out
204
- assert not "| modules.robots.include_allow" in out
204
+ assert "| modules.robots.include_allow" not in out
205
205
 
206
206
  # list output module options by module
207
207
  monkeypatch.setattr("sys.argv", ["bbot", "-om", "stdout", "-lmo"])
208
208
  result = await cli._main()
209
209
  out, err = capsys.readouterr()
210
- assert result == None
210
+ assert result is None
211
211
  assert out.count("modules.") == out.count("modules.stdout.")
212
212
 
213
213
  # list flags
214
214
  monkeypatch.setattr("sys.argv", ["bbot", "--list-flags"])
215
215
  result = await cli._main()
216
216
  out, err = capsys.readouterr()
217
- assert result == None
217
+ assert result is None
218
218
  assert "| safe " in out
219
219
  assert "| Non-intrusive, safe to run " in out
220
220
  assert "| active " in out
@@ -224,32 +224,32 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
224
224
  monkeypatch.setattr("sys.argv", ["bbot", "-f", "active", "--list-flags"])
225
225
  result = await cli._main()
226
226
  out, err = capsys.readouterr()
227
- assert result == None
228
- assert not "| safe " in out
227
+ assert result is None
228
+ assert "| safe " not in out
229
229
  assert "| active " in out
230
- assert not "| passive " in out
230
+ assert "| passive " not in out
231
231
 
232
232
  # list multiple flags
233
233
  monkeypatch.setattr("sys.argv", ["bbot", "-f", "active", "safe", "--list-flags"])
234
234
  result = await cli._main()
235
235
  out, err = capsys.readouterr()
236
- assert result == None
236
+ assert result is None
237
237
  assert "| safe " in out
238
238
  assert "| active " in out
239
- assert not "| passive " in out
239
+ assert "| passive " not in out
240
240
 
241
241
  # no args
242
242
  monkeypatch.setattr("sys.argv", ["bbot"])
243
243
  result = await cli._main()
244
244
  out, err = capsys.readouterr()
245
- assert result == None
245
+ assert result is None
246
246
  assert "Target:\n -t TARGET [TARGET ...]" in out
247
247
 
248
248
  # list modules
249
249
  monkeypatch.setattr("sys.argv", ["bbot", "-l"])
250
250
  result = await cli._main()
251
251
  out, err = capsys.readouterr()
252
- assert result == None
252
+ assert result is None
253
253
  assert "| dnsbrute " in out
254
254
  assert "| httpx " in out
255
255
  assert "| robots " in out
@@ -258,33 +258,33 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
258
258
  monkeypatch.setattr("sys.argv", ["bbot", "-f", "subdomain-enum", "-l"])
259
259
  result = await cli._main()
260
260
  out, err = capsys.readouterr()
261
- assert result == None
261
+ assert result is None
262
262
  assert "| dnsbrute " in out
263
263
  assert "| httpx " in out
264
- assert not "| robots " in out
264
+ assert "| robots " not in out
265
265
 
266
266
  # list modules by flag + required flag
267
267
  monkeypatch.setattr("sys.argv", ["bbot", "-f", "subdomain-enum", "-rf", "passive", "-l"])
268
268
  result = await cli._main()
269
269
  out, err = capsys.readouterr()
270
- assert result == None
270
+ assert result is None
271
271
  assert "| chaos " in out
272
- assert not "| httpx " in out
272
+ assert "| httpx " not in out
273
273
 
274
274
  # list modules by flag + excluded flag
275
275
  monkeypatch.setattr("sys.argv", ["bbot", "-f", "subdomain-enum", "-ef", "active", "-l"])
276
276
  result = await cli._main()
277
277
  out, err = capsys.readouterr()
278
- assert result == None
278
+ assert result is None
279
279
  assert "| chaos " in out
280
- assert not "| httpx " in out
280
+ assert "| httpx " not in out
281
281
 
282
282
  # list modules by flag + excluded module
283
283
  monkeypatch.setattr("sys.argv", ["bbot", "-f", "subdomain-enum", "-em", "dnsbrute", "-l"])
284
284
  result = await cli._main()
285
285
  out, err = capsys.readouterr()
286
- assert result == None
287
- assert not "| dnsbrute " in out
286
+ assert result is None
287
+ assert "| dnsbrute " not in out
288
288
  assert "| httpx " in out
289
289
 
290
290
  # output modules override
@@ -292,12 +292,12 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
292
292
  assert not caplog.text
293
293
  monkeypatch.setattr("sys.argv", ["bbot", "-om", "csv,json", "-y"])
294
294
  result = await cli._main()
295
- assert result == True
295
+ assert result is True
296
296
  assert "Loaded 2/2 output modules, (csv,json)" in caplog.text
297
297
  caplog.clear()
298
298
  monkeypatch.setattr("sys.argv", ["bbot", "-em", "csv,json", "-y"])
299
299
  result = await cli._main()
300
- assert result == True
300
+ assert result is True
301
301
  assert "Loaded 3/3 output modules, (python,stdout,txt)" in caplog.text
302
302
 
303
303
  # output modules override
@@ -305,7 +305,7 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
305
305
  assert not caplog.text
306
306
  monkeypatch.setattr("sys.argv", ["bbot", "-om", "subdomains", "-y"])
307
307
  result = await cli._main()
308
- assert result == True
308
+ assert result is True
309
309
  assert "Loaded 6/6 output modules, (csv,json,python,stdout,subdomains,txt)" in caplog.text
310
310
 
311
311
  # internal modules override
@@ -313,17 +313,17 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
313
313
  assert not caplog.text
314
314
  monkeypatch.setattr("sys.argv", ["bbot", "-y"])
315
315
  result = await cli._main()
316
- assert result == True
316
+ assert result is True
317
317
  assert "Loaded 5/5 internal modules (aggregate,cloudcheck,dnsresolve,excavate,speculate)" in caplog.text
318
318
  caplog.clear()
319
319
  monkeypatch.setattr("sys.argv", ["bbot", "-em", "excavate", "speculate", "-y"])
320
320
  result = await cli._main()
321
- assert result == True
321
+ assert result is True
322
322
  assert "Loaded 3/3 internal modules (aggregate,cloudcheck,dnsresolve)" in caplog.text
323
323
  caplog.clear()
324
324
  monkeypatch.setattr("sys.argv", ["bbot", "-c", "speculate=false", "-y"])
325
325
  result = await cli._main()
326
- assert result == True
326
+ assert result is True
327
327
  assert "Loaded 4/4 internal modules (aggregate,cloudcheck,dnsresolve,excavate)" in caplog.text
328
328
 
329
329
  # custom target type
@@ -331,7 +331,7 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
331
331
  monkeypatch.setattr("sys.argv", ["bbot", "-t", "ORG:evilcorp", "-y"])
332
332
  result = await cli._main()
333
333
  out, err = capsys.readouterr()
334
- assert result == True
334
+ assert result is True
335
335
  assert "[ORG_STUB] evilcorp TARGET" in out
336
336
 
337
337
  # activate modules by flag
@@ -339,58 +339,50 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
339
339
  assert not caplog.text
340
340
  monkeypatch.setattr("sys.argv", ["bbot", "-f", "passive"])
341
341
  result = await cli._main()
342
- assert result == True
342
+ assert result is True
343
343
 
344
344
  # unconsoleable output module
345
345
  monkeypatch.setattr("sys.argv", ["bbot", "-om", "web_report"])
346
346
  result = await cli._main()
347
- assert result == True
347
+ assert result is True
348
348
 
349
349
  # unresolved dependency
350
350
  monkeypatch.setattr("sys.argv", ["bbot", "-m", "wappalyzer"])
351
351
  result = await cli._main()
352
- assert result == True
353
-
354
- # enable and exclude the same module
355
- caplog.clear()
356
- assert not caplog.text
357
- monkeypatch.setattr("sys.argv", ["bbot", "-m", "ffuf_shortnames", "-em", "ffuf_shortnames"])
358
- result = await cli._main()
359
- assert result == None
360
- assert 'Unable to add scan module "ffuf_shortnames" because the module has been excluded' in caplog.text
352
+ assert result is True
361
353
 
362
354
  # require flags
363
355
  monkeypatch.setattr("sys.argv", ["bbot", "-f", "active", "-rf", "passive"])
364
356
  result = await cli._main()
365
- assert result == True
357
+ assert result is True
366
358
 
367
359
  # excluded flags
368
360
  monkeypatch.setattr("sys.argv", ["bbot", "-f", "active", "-ef", "active"])
369
361
  result = await cli._main()
370
- assert result == True
362
+ assert result is True
371
363
 
372
364
  # slow modules
373
365
  monkeypatch.setattr("sys.argv", ["bbot", "-m", "bucket_digitalocean"])
374
366
  result = await cli._main()
375
- assert result == True
367
+ assert result is True
376
368
 
377
369
  # deadly modules
378
370
  caplog.clear()
379
371
  assert not caplog.text
380
372
  monkeypatch.setattr("sys.argv", ["bbot", "-m", "nuclei"])
381
373
  result = await cli._main()
382
- assert result == False, "-m nuclei ran without --allow-deadly"
374
+ assert result is False, "-m nuclei ran without --allow-deadly"
383
375
  assert "Please specify --allow-deadly to continue" in caplog.text
384
376
 
385
377
  # --allow-deadly
386
378
  monkeypatch.setattr("sys.argv", ["bbot", "-m", "nuclei", "--allow-deadly"])
387
379
  result = await cli._main()
388
- assert result == True, "-m nuclei failed to run with --allow-deadly"
380
+ assert result is True, "-m nuclei failed to run with --allow-deadly"
389
381
 
390
382
  # install all deps
391
383
  monkeypatch.setattr("sys.argv", ["bbot", "--install-all-deps"])
392
384
  success = await cli._main()
393
- assert success == True, "--install-all-deps failed for at least one module"
385
+ assert success is True, "--install-all-deps failed for at least one module"
394
386
 
395
387
 
396
388
  @pytest.mark.asyncio
@@ -404,7 +396,7 @@ async def test_cli_customheaders(monkeypatch, caplog, capsys):
404
396
  "sys.argv", ["bbot", "--custom-headers", "foo=bar", "foo2=bar2", "foo3=bar=3", "--current-preset"]
405
397
  )
406
398
  success = await cli._main()
407
- assert success == None, "setting custom headers on command line failed"
399
+ assert success is None, "setting custom headers on command line failed"
408
400
  captured = capsys.readouterr()
409
401
  stdout_preset = yaml.safe_load(captured.out)
410
402
  assert stdout_preset["config"]["web"]["http_headers"] == {"foo": "bar", "foo2": "bar2", "foo3": "bar=3"}
@@ -412,21 +404,21 @@ async def test_cli_customheaders(monkeypatch, caplog, capsys):
412
404
  # test custom headers invalid (no "=")
413
405
  monkeypatch.setattr("sys.argv", ["bbot", "--custom-headers", "justastring", "--current-preset"])
414
406
  result = await cli._main()
415
- assert result == None
407
+ assert result is None
416
408
  assert "Custom headers not formatted correctly (missing '=')" in caplog.text
417
409
  caplog.clear()
418
410
 
419
411
  # test custom headers invalid (missing key)
420
412
  monkeypatch.setattr("sys.argv", ["bbot", "--custom-headers", "=nokey", "--current-preset"])
421
413
  result = await cli._main()
422
- assert result == None
414
+ assert result is None
423
415
  assert "Custom headers not formatted correctly (missing header name or value)" in caplog.text
424
416
  caplog.clear()
425
417
 
426
418
  # test custom headers invalid (missing value)
427
419
  monkeypatch.setattr("sys.argv", ["bbot", "--custom-headers", "missingvalue=", "--current-preset"])
428
420
  result = await cli._main()
429
- assert result == None
421
+ assert result is None
430
422
  assert "Custom headers not formatted correctly (missing header name or value)" in caplog.text
431
423
 
432
424
 
@@ -543,6 +535,13 @@ def test_cli_module_validation(monkeypatch, caplog):
543
535
  ]
544
536
  )
545
537
 
538
+ # bad target
539
+ caplog.clear()
540
+ assert not caplog.text
541
+ monkeypatch.setattr("sys.argv", ["bbot", "-t", "asdf:::sdf"])
542
+ cli.main()
543
+ assert 'Unable to autodetect event type from "asdf:::sdf"' in caplog.text
544
+
546
545
  # incorrect flag
547
546
  caplog.clear()
548
547
  assert not caplog.text
@@ -634,6 +633,35 @@ config:
634
633
  stdout_preset = yaml.safe_load(captured.out)
635
634
  assert stdout_preset["config"]["web"]["http_proxy"] == "http://proxy2"
636
635
 
636
+ # --fast-mode
637
+ monkeypatch.setattr("sys.argv", ["bbot", "--current-preset"])
638
+ cli.main()
639
+ captured = capsys.readouterr()
640
+ stdout_preset = yaml.safe_load(captured.out)
641
+ assert list(stdout_preset) == ["description"]
642
+
643
+ monkeypatch.setattr("sys.argv", ["bbot", "--fast", "--current-preset"])
644
+ cli.main()
645
+ captured = capsys.readouterr()
646
+ stdout_preset = yaml.safe_load(captured.out)
647
+ stdout_preset.pop("description")
648
+ assert stdout_preset == {
649
+ "config": {
650
+ "scope": {"strict": True},
651
+ "dns": {"minimal": True},
652
+ "modules": {"speculate": {"essential_only": True}},
653
+ },
654
+ "exclude_modules": ["excavate"],
655
+ }
656
+
657
+ # --proxy
658
+ monkeypatch.setattr("sys.argv", ["bbot", "--proxy", "http://127.0.0.1:8080", "--current-preset"])
659
+ cli.main()
660
+ captured = capsys.readouterr()
661
+ stdout_preset = yaml.safe_load(captured.out)
662
+ stdout_preset.pop("description")
663
+ assert stdout_preset == {"config": {"web": {"http_proxy": "http://127.0.0.1:8080"}}}
664
+
637
665
  # cli config overrides all presets
638
666
  monkeypatch.setattr(
639
667
  "sys.argv",
@@ -661,3 +689,49 @@ config:
661
689
 
662
690
  preset1_file.unlink()
663
691
  preset2_file.unlink()
692
+
693
+ # test output dir preset
694
+ output_dir_preset_file = bbot_test_dir / "output_dir_preset.yml"
695
+ scan_name = "cli_output_dir_test"
696
+ output_dir = bbot_test_dir / "cli_output_dir_preset"
697
+ scan_dir = output_dir / scan_name
698
+ output_file = scan_dir / "output.txt"
699
+
700
+ with open(output_dir_preset_file, "w") as f:
701
+ f.write(
702
+ f"""
703
+ output_dir: {output_dir}
704
+ scan_name: {scan_name}
705
+ """
706
+ )
707
+
708
+ assert not output_dir.exists()
709
+ assert not scan_dir.exists()
710
+ assert not output_file.exists()
711
+
712
+ monkeypatch.setattr("sys.argv", ["bbot", "-p", str(output_dir_preset_file.resolve()), "--current-preset"])
713
+ cli.main()
714
+ captured = capsys.readouterr()
715
+ stdout_preset = yaml.safe_load(captured.out)
716
+ assert stdout_preset["output_dir"] == str(output_dir)
717
+ assert stdout_preset["scan_name"] == scan_name
718
+
719
+ shutil.rmtree(output_dir, ignore_errors=True)
720
+ shutil.rmtree(scan_dir, ignore_errors=True)
721
+ shutil.rmtree(output_file, ignore_errors=True)
722
+
723
+ assert not output_dir.exists()
724
+ assert not scan_dir.exists()
725
+ assert not output_file.exists()
726
+
727
+ monkeypatch.setattr("sys.argv", ["bbot", "-p", str(output_dir_preset_file.resolve())])
728
+ cli.main()
729
+ captured = capsys.readouterr()
730
+ assert output_dir.is_dir()
731
+ assert scan_dir.is_dir()
732
+ assert output_file.is_file()
733
+
734
+ shutil.rmtree(output_dir, ignore_errors=True)
735
+ shutil.rmtree(scan_dir, ignore_errors=True)
736
+ shutil.rmtree(output_file, ignore_errors=True)
737
+ output_dir_preset_file.unlink()