bbot 2.3.0.5376rc0__py3-none-any.whl → 2.3.0.5384rc0__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 (143) hide show
  1. bbot/__init__.py +1 -1
  2. bbot/cli.py +2 -2
  3. bbot/core/config/logger.py +1 -1
  4. bbot/core/core.py +1 -1
  5. bbot/core/event/base.py +13 -13
  6. bbot/core/helpers/command.py +4 -4
  7. bbot/core/helpers/depsinstaller/installer.py +5 -5
  8. bbot/core/helpers/diff.py +7 -7
  9. bbot/core/helpers/dns/brute.py +1 -1
  10. bbot/core/helpers/dns/dns.py +1 -1
  11. bbot/core/helpers/dns/engine.py +4 -4
  12. bbot/core/helpers/files.py +1 -1
  13. bbot/core/helpers/helper.py +3 -1
  14. bbot/core/helpers/interactsh.py +3 -3
  15. bbot/core/helpers/misc.py +11 -11
  16. bbot/core/helpers/regex.py +1 -1
  17. bbot/core/helpers/regexes.py +3 -3
  18. bbot/core/helpers/validators.py +1 -1
  19. bbot/core/helpers/web/client.py +1 -1
  20. bbot/core/helpers/web/engine.py +1 -1
  21. bbot/core/helpers/web/web.py +2 -2
  22. bbot/core/helpers/wordcloud.py +5 -5
  23. bbot/core/modules.py +21 -21
  24. bbot/modules/azure_tenant.py +2 -2
  25. bbot/modules/base.py +16 -16
  26. bbot/modules/bypass403.py +5 -5
  27. bbot/modules/c99.py +1 -1
  28. bbot/modules/columbus.py +1 -1
  29. bbot/modules/deadly/ffuf.py +8 -8
  30. bbot/modules/deadly/nuclei.py +1 -1
  31. bbot/modules/deadly/vhost.py +3 -3
  32. bbot/modules/dnsbimi.py +1 -1
  33. bbot/modules/dnsdumpster.py +2 -2
  34. bbot/modules/dockerhub.py +1 -1
  35. bbot/modules/extractous.py +1 -1
  36. bbot/modules/filedownload.py +1 -1
  37. bbot/modules/generic_ssrf.py +3 -3
  38. bbot/modules/github_workflows.py +1 -1
  39. bbot/modules/gowitness.py +7 -7
  40. bbot/modules/host_header.py +5 -5
  41. bbot/modules/httpx.py +1 -1
  42. bbot/modules/iis_shortnames.py +6 -6
  43. bbot/modules/internal/cloudcheck.py +5 -5
  44. bbot/modules/internal/dnsresolve.py +7 -7
  45. bbot/modules/internal/excavate.py +5 -5
  46. bbot/modules/internal/speculate.py +4 -4
  47. bbot/modules/ipneighbor.py +1 -1
  48. bbot/modules/jadx.py +1 -1
  49. bbot/modules/newsletters.py +2 -2
  50. bbot/modules/output/asset_inventory.py +6 -6
  51. bbot/modules/output/base.py +1 -1
  52. bbot/modules/output/csv.py +1 -1
  53. bbot/modules/output/stdout.py +2 -2
  54. bbot/modules/paramminer_headers.py +3 -3
  55. bbot/modules/portscan.py +3 -3
  56. bbot/modules/report/asn.py +11 -11
  57. bbot/modules/robots.py +3 -3
  58. bbot/modules/securitytxt.py +1 -1
  59. bbot/modules/sitedossier.py +1 -1
  60. bbot/modules/social.py +1 -1
  61. bbot/modules/subdomainradar.py +1 -1
  62. bbot/modules/telerik.py +7 -7
  63. bbot/modules/templates/bucket.py +1 -1
  64. bbot/modules/templates/github.py +1 -1
  65. bbot/modules/templates/shodan.py +1 -1
  66. bbot/modules/templates/subdomain_enum.py +1 -1
  67. bbot/modules/templates/webhook.py +1 -1
  68. bbot/modules/trufflehog.py +1 -1
  69. bbot/modules/url_manipulation.py +3 -3
  70. bbot/modules/urlscan.py +1 -1
  71. bbot/modules/viewdns.py +1 -1
  72. bbot/modules/wafw00f.py +1 -1
  73. bbot/scanner/preset/args.py +10 -10
  74. bbot/scanner/preset/preset.py +9 -9
  75. bbot/scanner/scanner.py +17 -17
  76. bbot/scanner/target.py +1 -1
  77. bbot/scripts/docs.py +1 -1
  78. bbot/test/bbot_fixtures.py +1 -1
  79. bbot/test/conftest.py +1 -1
  80. bbot/test/run_tests.sh +4 -4
  81. bbot/test/test_step_1/test_bbot_fastapi.py +2 -2
  82. bbot/test/test_step_1/test_cli.py +56 -56
  83. bbot/test/test_step_1/test_dns.py +15 -15
  84. bbot/test/test_step_1/test_engine.py +17 -17
  85. bbot/test/test_step_1/test_events.py +22 -22
  86. bbot/test/test_step_1/test_helpers.py +26 -26
  87. bbot/test/test_step_1/test_manager_scope_accuracy.py +306 -306
  88. bbot/test/test_step_1/test_modules_basic.py +52 -53
  89. bbot/test/test_step_1/test_presets.py +81 -81
  90. bbot/test/test_step_1/test_regexes.py +5 -5
  91. bbot/test/test_step_1/test_scan.py +4 -4
  92. bbot/test/test_step_1/test_target.py +25 -25
  93. bbot/test/test_step_1/test_web.py +5 -5
  94. bbot/test/test_step_2/module_tests/base.py +6 -6
  95. bbot/test/test_step_2/module_tests/test_module_anubisdb.py +1 -1
  96. bbot/test/test_step_2/module_tests/test_module_azure_realm.py +1 -1
  97. bbot/test/test_step_2/module_tests/test_module_baddns.py +6 -6
  98. bbot/test/test_step_2/module_tests/test_module_baddns_direct.py +2 -4
  99. bbot/test/test_step_2/module_tests/test_module_bevigil.py +4 -4
  100. bbot/test/test_step_2/module_tests/test_module_binaryedge.py +2 -2
  101. bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py +2 -2
  102. bbot/test/test_step_2/module_tests/test_module_bucket_azure.py +1 -1
  103. bbot/test/test_step_2/module_tests/test_module_builtwith.py +2 -2
  104. bbot/test/test_step_2/module_tests/test_module_c99.py +9 -9
  105. bbot/test/test_step_2/module_tests/test_module_columbus.py +1 -1
  106. bbot/test/test_step_2/module_tests/test_module_credshed.py +2 -2
  107. bbot/test/test_step_2/module_tests/test_module_dehashed.py +1 -1
  108. bbot/test/test_step_2/module_tests/test_module_digitorus.py +1 -1
  109. bbot/test/test_step_2/module_tests/test_module_dnsbrute.py +8 -8
  110. bbot/test/test_step_2/module_tests/test_module_dnsdumpster.py +2 -2
  111. bbot/test/test_step_2/module_tests/test_module_excavate.py +10 -10
  112. bbot/test/test_step_2/module_tests/test_module_extractous.py +9 -9
  113. bbot/test/test_step_2/module_tests/test_module_filedownload.py +14 -14
  114. bbot/test/test_step_2/module_tests/test_module_git_clone.py +2 -2
  115. bbot/test/test_step_2/module_tests/test_module_gowitness.py +4 -4
  116. bbot/test/test_step_2/module_tests/test_module_host_header.py +1 -1
  117. bbot/test/test_step_2/module_tests/test_module_http.py +4 -4
  118. bbot/test/test_step_2/module_tests/test_module_httpx.py +7 -7
  119. bbot/test/test_step_2/module_tests/test_module_leakix.py +2 -2
  120. bbot/test/test_step_2/module_tests/test_module_myssl.py +1 -1
  121. bbot/test/test_step_2/module_tests/test_module_neo4j.py +1 -1
  122. bbot/test/test_step_2/module_tests/test_module_newsletters.py +6 -6
  123. bbot/test/test_step_2/module_tests/test_module_ntlm.py +7 -7
  124. bbot/test/test_step_2/module_tests/test_module_oauth.py +1 -1
  125. bbot/test/test_step_2/module_tests/test_module_otx.py +1 -1
  126. bbot/test/test_step_2/module_tests/test_module_paramminer_cookies.py +1 -1
  127. bbot/test/test_step_2/module_tests/test_module_paramminer_headers.py +2 -2
  128. bbot/test/test_step_2/module_tests/test_module_portscan.py +3 -3
  129. bbot/test/test_step_2/module_tests/test_module_postgres.py +1 -1
  130. bbot/test/test_step_2/module_tests/test_module_rapiddns.py +9 -9
  131. bbot/test/test_step_2/module_tests/test_module_sitedossier.py +2 -2
  132. bbot/test/test_step_2/module_tests/test_module_smuggler.py +1 -1
  133. bbot/test/test_step_2/module_tests/test_module_speculate.py +2 -6
  134. bbot/test/test_step_2/module_tests/test_module_splunk.py +4 -4
  135. bbot/test/test_step_2/module_tests/test_module_subdomaincenter.py +1 -1
  136. bbot/test/test_step_2/module_tests/test_module_subdomains.py +1 -1
  137. bbot/test/test_step_2/module_tests/test_module_trufflehog.py +2 -2
  138. bbot/test/test_step_2/module_tests/test_module_wayback.py +1 -1
  139. {bbot-2.3.0.5376rc0.dist-info → bbot-2.3.0.5384rc0.dist-info}/METADATA +2 -2
  140. {bbot-2.3.0.5376rc0.dist-info → bbot-2.3.0.5384rc0.dist-info}/RECORD +143 -143
  141. {bbot-2.3.0.5376rc0.dist-info → bbot-2.3.0.5384rc0.dist-info}/LICENSE +0 -0
  142. {bbot-2.3.0.5376rc0.dist-info → bbot-2.3.0.5384rc0.dist-info}/WHEEL +0 -0
  143. {bbot-2.3.0.5376rc0.dist-info → bbot-2.3.0.5384rc0.dist-info}/entry_points.txt +0 -0
bbot/core/modules.py CHANGED
@@ -153,7 +153,7 @@ class ModuleLoader:
153
153
  else:
154
154
  log.debug(f"Preloading {module_name} from disk")
155
155
  if module_dir.name == "modules":
156
- namespace = f"bbot.modules"
156
+ namespace = "bbot.modules"
157
157
  else:
158
158
  namespace = f"bbot.modules.{module_dir.name}"
159
159
  try:
@@ -235,7 +235,7 @@ class ModuleLoader:
235
235
  return self.__preloaded
236
236
 
237
237
  def get_recursive_dirs(self, *dirs):
238
- dirs = set(Path(d).resolve() for d in dirs)
238
+ dirs = {Path(d).resolve() for d in dirs}
239
239
  for d in list(dirs):
240
240
  if not d.is_dir():
241
241
  continue
@@ -340,70 +340,70 @@ class ModuleLoader:
340
340
  # class attributes that are dictionaries
341
341
  if type(class_attr) == ast.Assign and type(class_attr.value) == ast.Dict:
342
342
  # module options
343
- if any([target.id == "options" for target in class_attr.targets]):
343
+ if any(target.id == "options" for target in class_attr.targets):
344
344
  config.update(ast.literal_eval(class_attr.value))
345
345
  # module options
346
- elif any([target.id == "options_desc" for target in class_attr.targets]):
346
+ elif any(target.id == "options_desc" for target in class_attr.targets):
347
347
  options_desc.update(ast.literal_eval(class_attr.value))
348
348
  # module metadata
349
- elif any([target.id == "meta" for target in class_attr.targets]):
349
+ elif any(target.id == "meta" for target in class_attr.targets):
350
350
  meta = ast.literal_eval(class_attr.value)
351
351
 
352
352
  # class attributes that are lists
353
353
  if type(class_attr) == ast.Assign and type(class_attr.value) == ast.List:
354
354
  # flags
355
- if any([target.id == "flags" for target in class_attr.targets]):
355
+ if any(target.id == "flags" for target in class_attr.targets):
356
356
  for flag in class_attr.value.elts:
357
357
  if type(flag.value) == str:
358
358
  flags.add(flag.value)
359
359
  # watched events
360
- elif any([target.id == "watched_events" for target in class_attr.targets]):
360
+ elif any(target.id == "watched_events" for target in class_attr.targets):
361
361
  for event_type in class_attr.value.elts:
362
362
  if type(event_type.value) == str:
363
363
  watched_events.add(event_type.value)
364
364
  # produced events
365
- elif any([target.id == "produced_events" for target in class_attr.targets]):
365
+ elif any(target.id == "produced_events" for target in class_attr.targets):
366
366
  for event_type in class_attr.value.elts:
367
367
  if type(event_type.value) == str:
368
368
  produced_events.add(event_type.value)
369
369
 
370
370
  # bbot module dependencies
371
- elif any([target.id == "deps_modules" for target in class_attr.targets]):
371
+ elif any(target.id == "deps_modules" for target in class_attr.targets):
372
372
  for dep_module in class_attr.value.elts:
373
373
  if type(dep_module.value) == str:
374
374
  deps_modules.add(dep_module.value)
375
375
  # python dependencies
376
- elif any([target.id == "deps_pip" for target in class_attr.targets]):
376
+ elif any(target.id == "deps_pip" for target in class_attr.targets):
377
377
  for dep_pip in class_attr.value.elts:
378
378
  if type(dep_pip.value) == str:
379
379
  deps_pip.append(dep_pip.value)
380
- elif any([target.id == "deps_pip_constraints" for target in class_attr.targets]):
380
+ elif any(target.id == "deps_pip_constraints" for target in class_attr.targets):
381
381
  for dep_pip in class_attr.value.elts:
382
382
  if type(dep_pip.value) == str:
383
383
  deps_pip_constraints.append(dep_pip.value)
384
384
  # apt dependencies
385
- elif any([target.id == "deps_apt" for target in class_attr.targets]):
385
+ elif any(target.id == "deps_apt" for target in class_attr.targets):
386
386
  for dep_apt in class_attr.value.elts:
387
387
  if type(dep_apt.value) == str:
388
388
  deps_apt.append(dep_apt.value)
389
389
  # bash dependencies
390
- elif any([target.id == "deps_shell" for target in class_attr.targets]):
390
+ elif any(target.id == "deps_shell" for target in class_attr.targets):
391
391
  for dep_shell in class_attr.value.elts:
392
392
  deps_shell.append(ast.literal_eval(dep_shell))
393
393
  # ansible playbook
394
- elif any([target.id == "deps_ansible" for target in class_attr.targets]):
394
+ elif any(target.id == "deps_ansible" for target in class_attr.targets):
395
395
  ansible_tasks = ast.literal_eval(class_attr.value)
396
396
  # shared/common module dependencies
397
- elif any([target.id == "deps_common" for target in class_attr.targets]):
397
+ elif any(target.id == "deps_common" for target in class_attr.targets):
398
398
  for dep_common in class_attr.value.elts:
399
399
  if type(dep_common.value) == str:
400
400
  deps_common.append(dep_common.value)
401
401
 
402
402
  for task in ansible_tasks:
403
- if not "become" in task:
403
+ if "become" not in task:
404
404
  task["become"] = False
405
405
  # don't sudo brew
406
- elif os_platform() == "darwin" and ("package" in task and task.get("become", False) == True):
406
+ elif os_platform() == "darwin" and ("package" in task and task.get("become", False) is True):
407
407
  task["become"] = False
408
408
 
409
409
  preloaded_data = {
@@ -436,8 +436,8 @@ class ModuleLoader:
436
436
  f'Error while preloading module "{module_file}": No shared dependency named "{dep_common}" (choices: {common_choices})'
437
437
  )
438
438
  for ansible_task in ansible_task_list:
439
- if any(x == True for x in search_dict_by_key("become", ansible_task)) or any(
440
- x == True for x in search_dict_by_key("ansible_become", ansible_tasks)
439
+ if any(x is True for x in search_dict_by_key("become", ansible_task)) or any(
440
+ x is True for x in search_dict_by_key("ansible_become", ansible_tasks)
441
441
  ):
442
442
  preloaded_data["sudo"] = True
443
443
  return preloaded_data
@@ -540,7 +540,7 @@ class ModuleLoader:
540
540
  with suppress(KeyError):
541
541
  choices.remove(modname)
542
542
  if event_type not in resolve_choices:
543
- resolve_choices[event_type] = dict()
543
+ resolve_choices[event_type] = {}
544
544
  deps = resolve_choices[event_type]
545
545
  self.add_or_create(deps, "required_by", modname)
546
546
  for c in choices:
@@ -639,7 +639,7 @@ class ModuleLoader:
639
639
  def modules_options_table(self, modules=None, mod_type=None):
640
640
  table = []
641
641
  header = ["Config Option", "Type", "Description", "Default"]
642
- for module_name, module_options in self.modules_options(modules, mod_type).items():
642
+ for module_options in self.modules_options(modules, mod_type).values():
643
643
  table += module_options
644
644
  return make_table(table, header)
645
645
 
@@ -102,7 +102,7 @@ class azure_tenant(BaseModule):
102
102
  status_code = getattr(r, "status_code", 0)
103
103
  if status_code not in (200, 421):
104
104
  self.verbose(f'Error retrieving azure_tenant domains for "{domain}" (status code: {status_code})')
105
- return set(), dict()
105
+ return set(), {}
106
106
  found_domains = list(set(await self.helpers.re.findall(self.d_xml_regex, r.text)))
107
107
  domains = set()
108
108
 
@@ -116,7 +116,7 @@ class azure_tenant(BaseModule):
116
116
  self.scan.word_cloud.absorb_word(d)
117
117
 
118
118
  r = await openid_task
119
- openid_config = dict()
119
+ openid_config = {}
120
120
  with suppress(Exception):
121
121
  openid_config = r.json()
122
122
 
bbot/modules/base.py CHANGED
@@ -311,7 +311,7 @@ class BaseModule:
311
311
  if self.auth_secret:
312
312
  try:
313
313
  await self.ping()
314
- self.hugesuccess(f"API is ready")
314
+ self.hugesuccess("API is ready")
315
315
  return True, ""
316
316
  except Exception as e:
317
317
  self.trace(traceback.format_exc())
@@ -332,10 +332,10 @@ class BaseModule:
332
332
 
333
333
  def cycle_api_key(self):
334
334
  if len(self._api_keys) > 1:
335
- self.verbose(f"Cycling API key")
335
+ self.verbose("Cycling API key")
336
336
  self._api_keys.insert(0, self._api_keys.pop())
337
337
  else:
338
- self.debug(f"No extra API keys to cycle")
338
+ self.debug("No extra API keys to cycle")
339
339
 
340
340
  @property
341
341
  def api_retries(self):
@@ -669,7 +669,7 @@ class BaseModule:
669
669
  if self.incoming_event_queue is not False:
670
670
  event = await self.incoming_event_queue.get()
671
671
  else:
672
- self.debug(f"Event queue is in bad state")
672
+ self.debug("Event queue is in bad state")
673
673
  break
674
674
  except asyncio.queues.QueueEmpty:
675
675
  continue
@@ -700,7 +700,7 @@ class BaseModule:
700
700
  else:
701
701
  self.error(f"Critical failure in module {self.name}: {e}")
702
702
  self.error(traceback.format_exc())
703
- self.log.trace(f"Worker stopped")
703
+ self.log.trace("Worker stopped")
704
704
 
705
705
  @property
706
706
  def max_scope_distance(self):
@@ -743,7 +743,7 @@ class BaseModule:
743
743
  if event.type in ("FINISHED",):
744
744
  return True, "its type is FINISHED"
745
745
  if self.errored:
746
- return False, f"module is in error state"
746
+ return False, "module is in error state"
747
747
  # exclude non-watched types
748
748
  if not any(t in self.get_watched_events() for t in ("*", event.type)):
749
749
  return False, "its type is not in watched_events"
@@ -770,7 +770,7 @@ class BaseModule:
770
770
  # check duplicates
771
771
  is_incoming_duplicate, reason = self.is_incoming_duplicate(event, add=True)
772
772
  if is_incoming_duplicate and not self.accept_dupes:
773
- return False, f"module has already seen it" + (f" ({reason})" if reason else "")
773
+ return False, "module has already seen it" + (f" ({reason})" if reason else "")
774
774
 
775
775
  return acceptable, reason
776
776
 
@@ -863,7 +863,7 @@ class BaseModule:
863
863
  """
864
864
  async with self._task_counter.count("queue_event()", _log=False):
865
865
  if self.incoming_event_queue is False:
866
- self.debug(f"Not in an acceptable state to queue incoming event")
866
+ self.debug("Not in an acceptable state to queue incoming event")
867
867
  return
868
868
  acceptable, reason = self._event_precheck(event)
869
869
  if not acceptable:
@@ -879,7 +879,7 @@ class BaseModule:
879
879
  if event.type != "FINISHED":
880
880
  self.scan._new_activity = True
881
881
  except AttributeError:
882
- self.debug(f"Not in an acceptable state to queue incoming event")
882
+ self.debug("Not in an acceptable state to queue incoming event")
883
883
 
884
884
  async def queue_outgoing_event(self, event, **kwargs):
885
885
  """
@@ -904,7 +904,7 @@ class BaseModule:
904
904
  try:
905
905
  await self.outgoing_event_queue.put((event, kwargs))
906
906
  except AttributeError:
907
- self.debug(f"Not in an acceptable state to queue outgoing event")
907
+ self.debug("Not in an acceptable state to queue outgoing event")
908
908
 
909
909
  def set_error_state(self, message=None, clear_outgoing_queue=False, critical=False):
910
910
  """
@@ -939,7 +939,7 @@ class BaseModule:
939
939
  self.errored = True
940
940
  # clear incoming queue
941
941
  if self.incoming_event_queue is not False:
942
- self.debug(f"Emptying event_queue")
942
+ self.debug("Emptying event_queue")
943
943
  with suppress(asyncio.queues.QueueEmpty):
944
944
  while 1:
945
945
  self.incoming_event_queue.get_nowait()
@@ -1126,7 +1126,7 @@ class BaseModule:
1126
1126
  """
1127
1127
  if self.api_key:
1128
1128
  url = url.format(api_key=self.api_key)
1129
- if not "headers" in kwargs:
1129
+ if "headers" not in kwargs:
1130
1130
  kwargs["headers"] = {}
1131
1131
  kwargs["headers"]["Authorization"] = f"Bearer {self.api_key}"
1132
1132
  return url, kwargs
@@ -1142,7 +1142,7 @@ class BaseModule:
1142
1142
 
1143
1143
  # loop until we have a successful request
1144
1144
  for _ in range(self.api_retries):
1145
- if not "headers" in kwargs:
1145
+ if "headers" not in kwargs:
1146
1146
  kwargs["headers"] = {}
1147
1147
  new_url, kwargs = self.prepare_api_request(url, kwargs)
1148
1148
  kwargs["url"] = new_url
@@ -1589,7 +1589,7 @@ class BaseInterceptModule(BaseModule):
1589
1589
  event = incoming
1590
1590
  kwargs = {}
1591
1591
  else:
1592
- self.debug(f"Event queue is in bad state")
1592
+ self.debug("Event queue is in bad state")
1593
1593
  break
1594
1594
  except asyncio.queues.QueueEmpty:
1595
1595
  await asyncio.sleep(0.1)
@@ -1644,7 +1644,7 @@ class BaseInterceptModule(BaseModule):
1644
1644
  else:
1645
1645
  self.critical(f"Critical failure in intercept module {self.name}: {e}")
1646
1646
  self.critical(traceback.format_exc())
1647
- self.log.trace(f"Worker stopped")
1647
+ self.log.trace("Worker stopped")
1648
1648
 
1649
1649
  async def get_incoming_event(self):
1650
1650
  """
@@ -1675,7 +1675,7 @@ class BaseInterceptModule(BaseModule):
1675
1675
  try:
1676
1676
  self.incoming_event_queue.put_nowait((event, kwargs))
1677
1677
  except AttributeError:
1678
- self.debug(f"Not in an acceptable state to queue incoming event")
1678
+ self.debug("Not in an acceptable state to queue incoming event")
1679
1679
 
1680
1680
  async def _event_postcheck(self, event):
1681
1681
  return await self._event_postcheck_inner(event)
bbot/modules/bypass403.py CHANGED
@@ -92,7 +92,7 @@ class bypass403(BaseModule):
92
92
  return None
93
93
 
94
94
  sig = self.format_signature(sig, event)
95
- if sig[2] != None:
95
+ if sig[2] is not None:
96
96
  headers = dict(sig[2])
97
97
  else:
98
98
  headers = None
@@ -106,13 +106,13 @@ class bypass403(BaseModule):
106
106
  continue
107
107
 
108
108
  # In some cases WAFs will respond with a 200 code which causes a false positive
109
- if subject_response != None:
109
+ if subject_response is not None:
110
110
  for ws in waf_strings:
111
111
  if ws in subject_response.text:
112
112
  self.debug("Rejecting result based on presence of WAF string")
113
113
  return
114
114
 
115
- if match == False:
115
+ if match is False:
116
116
  if str(subject_response.status_code)[0] != "4":
117
117
  if sig[2]:
118
118
  added_header_tuple = next(iter(sig[2].items()))
@@ -165,13 +165,13 @@ class bypass403(BaseModule):
165
165
  return False
166
166
 
167
167
  def format_signature(self, sig, event):
168
- if sig[3] == True:
168
+ if sig[3] is True:
169
169
  cleaned_path = event.parsed_url.path.strip("/")
170
170
  else:
171
171
  cleaned_path = event.parsed_url.path.lstrip("/")
172
172
  kwargs = {"scheme": event.parsed_url.scheme, "netloc": event.parsed_url.netloc, "path": cleaned_path}
173
173
  formatted_url = sig[1].format(**kwargs)
174
- if sig[2] != None:
174
+ if sig[2] is not None:
175
175
  formatted_headers = {k: v.format(**kwargs) for k, v in sig[2].items()}
176
176
  else:
177
177
  formatted_headers = None
bbot/modules/c99.py CHANGED
@@ -20,7 +20,7 @@ class c99(subdomain_enum_apikey):
20
20
  async def ping(self):
21
21
  url = f"{self.base_url}/randomnumber?key={{api_key}}&between=1,100&json"
22
22
  response = await self.api_request(url)
23
- assert response.json()["success"] == True, getattr(response, "text", "no response from server")
23
+ assert response.json()["success"] is True, getattr(response, "text", "no response from server")
24
24
 
25
25
  async def request_url(self, query):
26
26
  url = f"{self.base_url}/subdomainfinder?key={{api_key}}&domain={self.helpers.quote(query)}&json"
bbot/modules/columbus.py CHANGED
@@ -21,5 +21,5 @@ class columbus(subdomain_enum):
21
21
  results = set()
22
22
  json = r.json()
23
23
  if json and isinstance(json, list):
24
- return set([f"{s.lower()}.{query}" for s in json])
24
+ return {f"{s.lower()}.{query}" for s in json}
25
25
  return results
@@ -28,7 +28,7 @@ class ffuf(BaseModule):
28
28
 
29
29
  deps_common = ["ffuf"]
30
30
 
31
- banned_characters = set([" "])
31
+ banned_characters = {" "}
32
32
  blacklist = ["images", "css", "image"]
33
33
 
34
34
  in_scope_only = True
@@ -52,7 +52,7 @@ class ffuf(BaseModule):
52
52
 
53
53
  async def handle_event(self, event):
54
54
  if self.helpers.url_depth(event.data) > self.config.get("max_depth"):
55
- self.debug(f"Exceeded max depth, aborting event")
55
+ self.debug("Exceeded max depth, aborting event")
56
56
  return
57
57
 
58
58
  # only FFUF against a directory
@@ -122,7 +122,7 @@ class ffuf(BaseModule):
122
122
  continue
123
123
 
124
124
  # if the codes are different, we should abort, this should also be a warning, as it is highly unusual behavior
125
- if len(set(d["status"] for d in canary_results)) != 1:
125
+ if len({d["status"] for d in canary_results}) != 1:
126
126
  self.warning("Got different codes for each baseline. This could indicate load balancing")
127
127
  filters[ext] = ["ABORT", "BASELINE_CHANGED_CODES"]
128
128
  continue
@@ -148,7 +148,7 @@ class ffuf(BaseModule):
148
148
  continue
149
149
 
150
150
  # we start by seeing if all of the baselines have the same character count
151
- if len(set(d["length"] for d in canary_results)) == 1:
151
+ if len({d["length"] for d in canary_results}) == 1:
152
152
  self.debug("All baseline results had the same char count, we can make a filter on that")
153
153
  filters[ext] = [
154
154
  "-fc",
@@ -161,7 +161,7 @@ class ffuf(BaseModule):
161
161
  continue
162
162
 
163
163
  # if that doesn't work we can try words
164
- if len(set(d["words"] for d in canary_results)) == 1:
164
+ if len({d["words"] for d in canary_results}) == 1:
165
165
  self.debug("All baseline results had the same word count, we can make a filter on that")
166
166
  filters[ext] = [
167
167
  "-fc",
@@ -174,7 +174,7 @@ class ffuf(BaseModule):
174
174
  continue
175
175
 
176
176
  # as a last resort we will try lines
177
- if len(set(d["lines"] for d in canary_results)) == 1:
177
+ if len({d["lines"] for d in canary_results}) == 1:
178
178
  self.debug("All baseline results had the same word count, we can make a filter on that")
179
179
  filters[ext] = [
180
180
  "-fc",
@@ -252,7 +252,7 @@ class ffuf(BaseModule):
252
252
  self.warning(f"Exiting from FFUF run early, received an ABORT filter: [{filters[ext][1]}]")
253
253
  continue
254
254
 
255
- elif filters[ext] == None:
255
+ elif filters[ext] is None:
256
256
  pass
257
257
 
258
258
  else:
@@ -282,7 +282,7 @@ class ffuf(BaseModule):
282
282
  else:
283
283
  if mode == "normal":
284
284
  # before emitting, we are going to send another baseline. This will immediately catch things like a WAF flipping blocking on us mid-scan
285
- if baseline == False:
285
+ if baseline is False:
286
286
  pre_emit_temp_canary = [
287
287
  f
288
288
  async for f in self.execute_ffuf(
@@ -226,7 +226,7 @@ class nuclei(BaseModule):
226
226
  command.append(f"-{cli_option}")
227
227
  command.append(option)
228
228
 
229
- if self.scan.config.get("interactsh_disable") == True:
229
+ if self.scan.config.get("interactsh_disable") is True:
230
230
  self.info("Disbling interactsh in accordance with global settings")
231
231
  command.append("-no-interactsh")
232
232
 
@@ -23,7 +23,7 @@ class vhost(ffuf):
23
23
  }
24
24
 
25
25
  deps_common = ["ffuf"]
26
- banned_characters = set([" ", "."])
26
+ banned_characters = {" ", "."}
27
27
 
28
28
  in_scope_only = True
29
29
 
@@ -73,7 +73,7 @@ class vhost(ffuf):
73
73
 
74
74
  async def ffuf_vhost(self, host, basehost, event, wordlist=None, skip_dns_host=False):
75
75
  filters = await self.baseline_ffuf(f"{host}/", exts=[""], suffix=basehost, mode="hostheader")
76
- self.debug(f"Baseline completed and returned these filters:")
76
+ self.debug("Baseline completed and returned these filters:")
77
77
  self.debug(filters)
78
78
  if not wordlist:
79
79
  wordlist = self.tempfile
@@ -90,7 +90,7 @@ class vhost(ffuf):
90
90
  parent=event,
91
91
  context=f"{{module}} brute-forced virtual hosts for {event.data} and found {{event.type}}: {vhost_str}",
92
92
  )
93
- if skip_dns_host == False:
93
+ if skip_dns_host is False:
94
94
  await self.emit_event(
95
95
  f"{vhost_dict['vhost']}{basehost}",
96
96
  "DNS_NAME",
bbot/modules/dnsbimi.py CHANGED
@@ -80,7 +80,7 @@ class dnsbimi(BaseModule):
80
80
  return False, "event is wildcard"
81
81
 
82
82
  # there's no value in inspecting service records
83
- if service_record(event.host) == True:
83
+ if service_record(event.host) is True:
84
84
  return False, "service record detected"
85
85
 
86
86
  return True
@@ -31,7 +31,7 @@ class dnsdumpster(subdomain_enum):
31
31
 
32
32
  html = self.helpers.beautifulsoup(res1.content, "html.parser")
33
33
  if html is False:
34
- self.verbose(f"BeautifulSoup returned False")
34
+ self.verbose("BeautifulSoup returned False")
35
35
  return ret
36
36
 
37
37
  csrftoken = None
@@ -82,7 +82,7 @@ class dnsdumpster(subdomain_enum):
82
82
  return ret
83
83
  html = self.helpers.beautifulsoup(res2.content, "html.parser")
84
84
  if html is False:
85
- self.verbose(f"BeautifulSoup returned False")
85
+ self.verbose("BeautifulSoup returned False")
86
86
  return ret
87
87
  escaped_domain = re.escape(domain)
88
88
  match_pattern = re.compile(r"^[\w\.-]+\." + escaped_domain + r"$")
bbot/modules/dockerhub.py CHANGED
@@ -31,7 +31,7 @@ class dockerhub(BaseModule):
31
31
  async def handle_org_stub(self, event):
32
32
  profile_name = event.data
33
33
  # docker usernames are case sensitive, so if there are capitalizations we also try a lowercase variation
34
- profiles_to_check = set([profile_name, profile_name.lower()])
34
+ profiles_to_check = {profile_name, profile_name.lower()}
35
35
  for p in profiles_to_check:
36
36
  api_url = f"{self.api_url}/users/{p}"
37
37
  api_result = await self.helpers.request(api_url, follow_redirects=True)
@@ -67,7 +67,7 @@ class extractous(BaseModule):
67
67
  scope_distance_modifier = 1
68
68
 
69
69
  async def setup(self):
70
- self.extensions = list(set([e.lower().strip(".") for e in self.config.get("extensions", [])]))
70
+ self.extensions = list({e.lower().strip(".") for e in self.config.get("extensions", [])})
71
71
  return True
72
72
 
73
73
  async def filter_event(self, event):
@@ -87,7 +87,7 @@ class filedownload(BaseModule):
87
87
  scope_distance_modifier = 3
88
88
 
89
89
  async def setup(self):
90
- self.extensions = list(set([e.lower().strip(".") for e in self.config.get("extensions", [])]))
90
+ self.extensions = list({e.lower().strip(".") for e in self.config.get("extensions", [])})
91
91
  self.max_filesize = self.config.get("max_filesize", "10MB")
92
92
  self.download_dir = self.scan.home / "filedownload"
93
93
  self.helpers.mkdir(self.download_dir)
@@ -163,7 +163,7 @@ class generic_ssrf(BaseModule):
163
163
  self.severity = None
164
164
  self.generic_only = self.config.get("generic_only", False)
165
165
 
166
- if self.scan.config.get("interactsh_disable", False) == False:
166
+ if self.scan.config.get("interactsh_disable", False) is False:
167
167
  try:
168
168
  self.interactsh_instance = self.helpers.interactsh()
169
169
  self.interactsh_domain = await self.interactsh_instance.register(callback=self.interactsh_callback)
@@ -216,7 +216,7 @@ class generic_ssrf(BaseModule):
216
216
  self.debug("skipping result because subdomain tag was missing")
217
217
 
218
218
  async def cleanup(self):
219
- if self.scan.config.get("interactsh_disable", False) == False:
219
+ if self.scan.config.get("interactsh_disable", False) is False:
220
220
  try:
221
221
  await self.interactsh_instance.deregister()
222
222
  self.debug(
@@ -226,7 +226,7 @@ class generic_ssrf(BaseModule):
226
226
  self.warning(f"Interactsh failure: {e}")
227
227
 
228
228
  async def finish(self):
229
- if self.scan.config.get("interactsh_disable", False) == False:
229
+ if self.scan.config.get("interactsh_disable", False) is False:
230
230
  await self.helpers.sleep(5)
231
231
  try:
232
232
  for r in await self.interactsh_instance.poll():
@@ -166,7 +166,7 @@ class github_workflows(github):
166
166
  main_logs = []
167
167
  with zipfile.ZipFile(file_destination, "r") as logzip:
168
168
  for name in logzip.namelist():
169
- if fnmatch.fnmatch(name, "*.txt") and not "/" in name:
169
+ if fnmatch.fnmatch(name, "*.txt") and "/" not in name:
170
170
  logzip.extract(name, folder)
171
171
  main_logs.append(folder / name)
172
172
  return main_logs
bbot/modules/gowitness.py CHANGED
@@ -88,7 +88,7 @@ class gowitness(BaseModule):
88
88
  self.screenshot_path = self.base_path / "screenshots"
89
89
  self.command = self.construct_command()
90
90
  self.prepped = False
91
- self.screenshots_taken = dict()
91
+ self.screenshots_taken = {}
92
92
  self.connections_logged = set()
93
93
  self.technologies_found = set()
94
94
  return True
@@ -172,7 +172,7 @@ class gowitness(BaseModule):
172
172
 
173
173
  # emit technologies
174
174
  new_technologies = await self.get_new_technologies()
175
- for _, row in new_technologies.items():
175
+ for row in new_technologies.values():
176
176
  parent_id = row["url_id"]
177
177
  parent_url = self.screenshots_taken[parent_id]
178
178
  parent_event = event_dict[parent_url]
@@ -227,7 +227,7 @@ class gowitness(BaseModule):
227
227
  return screenshots
228
228
 
229
229
  async def get_new_network_logs(self):
230
- network_logs = dict()
230
+ network_logs = {}
231
231
  if self.db_path.is_file():
232
232
  async with aiosqlite.connect(str(self.db_path)) as con:
233
233
  con.row_factory = aiosqlite.Row
@@ -241,7 +241,7 @@ class gowitness(BaseModule):
241
241
  return network_logs
242
242
 
243
243
  async def get_new_technologies(self):
244
- technologies = dict()
244
+ technologies = {}
245
245
  if self.db_path.is_file():
246
246
  async with aiosqlite.connect(str(self.db_path)) as con:
247
247
  con.row_factory = aiosqlite.Row
@@ -264,8 +264,8 @@ class gowitness(BaseModule):
264
264
  async def report(self):
265
265
  if self.screenshots_taken:
266
266
  self.success(f"{len(self.screenshots_taken):,} web screenshots captured. To view:")
267
- self.success(f" - Start gowitness")
267
+ self.success(" - Start gowitness")
268
268
  self.success(f" - cd {self.base_path} && ./gowitness server")
269
- self.success(f" - Browse to http://localhost:7171")
269
+ self.success(" - Browse to http://localhost:7171")
270
270
  else:
271
- self.info(f"No web screenshots captured")
271
+ self.info("No web screenshots captured")
@@ -19,7 +19,7 @@ class host_header(BaseModule):
19
19
 
20
20
  async def setup(self):
21
21
  self.subdomain_tags = {}
22
- if self.scan.config.get("interactsh_disable", False) == False:
22
+ if self.scan.config.get("interactsh_disable", False) is False:
23
23
  try:
24
24
  self.interactsh_instance = self.helpers.interactsh()
25
25
  self.domain = await self.interactsh_instance.register(callback=self.interactsh_callback)
@@ -60,7 +60,7 @@ class host_header(BaseModule):
60
60
  self.debug("skipping results because subdomain tag was missing")
61
61
 
62
62
  async def finish(self):
63
- if self.scan.config.get("interactsh_disable", False) == False:
63
+ if self.scan.config.get("interactsh_disable", False) is False:
64
64
  await self.helpers.sleep(5)
65
65
  try:
66
66
  for r in await self.interactsh_instance.poll():
@@ -69,7 +69,7 @@ class host_header(BaseModule):
69
69
  self.debug(f"Error in interact.sh: {e}")
70
70
 
71
71
  async def cleanup(self):
72
- if self.scan.config.get("interactsh_disable", False) == False:
72
+ if self.scan.config.get("interactsh_disable", False) is False:
73
73
  try:
74
74
  await self.interactsh_instance.deregister()
75
75
  self.debug(
@@ -84,7 +84,7 @@ class host_header(BaseModule):
84
84
 
85
85
  added_cookies = {}
86
86
 
87
- for header, header_values in event.data["header-dict"].items():
87
+ for header_values in event.data["header-dict"].values():
88
88
  for header_value in header_values:
89
89
  if header_value.lower() == "set-cookie":
90
90
  header_split = header_value.split("=")
@@ -136,7 +136,7 @@ class host_header(BaseModule):
136
136
 
137
137
  split_output = output.split("\n")
138
138
  if " 4" in split_output:
139
- description = f"Duplicate Host Header Tolerated"
139
+ description = "Duplicate Host Header Tolerated"
140
140
  await self.emit_event(
141
141
  {
142
142
  "host": str(event.host),
bbot/modules/httpx.py CHANGED
@@ -90,7 +90,7 @@ class httpx(BaseModule):
90
90
  else:
91
91
  url = str(event.data)
92
92
  url_hash = hash((event.host, event.port, has_spider_max))
93
- if url_hash == None:
93
+ if url_hash is None:
94
94
  url_hash = hash((url, has_spider_max))
95
95
  return url, url_hash
96
96