secator 0.7.0__py3-none-any.whl → 0.8.0__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 secator might be problematic. Click here for more details.

Files changed (49) hide show
  1. secator/celery.py +3 -3
  2. secator/cli.py +106 -76
  3. secator/config.py +88 -58
  4. secator/configs/workflows/subdomain_recon.yaml +2 -2
  5. secator/configs/workflows/url_dirsearch.yaml +1 -1
  6. secator/decorators.py +1 -0
  7. secator/definitions.py +1 -1
  8. secator/installer.py +277 -60
  9. secator/output_types/error.py +3 -3
  10. secator/output_types/exploit.py +11 -7
  11. secator/output_types/info.py +2 -2
  12. secator/output_types/ip.py +1 -1
  13. secator/output_types/port.py +3 -3
  14. secator/output_types/record.py +4 -4
  15. secator/output_types/stat.py +2 -2
  16. secator/output_types/subdomain.py +1 -1
  17. secator/output_types/tag.py +3 -3
  18. secator/output_types/target.py +2 -2
  19. secator/output_types/url.py +11 -11
  20. secator/output_types/user_account.py +6 -6
  21. secator/output_types/vulnerability.py +5 -4
  22. secator/output_types/warning.py +2 -2
  23. secator/report.py +1 -0
  24. secator/runners/_base.py +17 -13
  25. secator/runners/command.py +44 -7
  26. secator/tasks/_categories.py +145 -43
  27. secator/tasks/bbot.py +2 -0
  28. secator/tasks/bup.py +1 -0
  29. secator/tasks/dirsearch.py +2 -2
  30. secator/tasks/dnsxbrute.py +2 -1
  31. secator/tasks/feroxbuster.py +2 -3
  32. secator/tasks/fping.py +1 -1
  33. secator/tasks/grype.py +2 -4
  34. secator/tasks/h8mail.py +1 -1
  35. secator/tasks/katana.py +1 -1
  36. secator/tasks/maigret.py +1 -1
  37. secator/tasks/msfconsole.py +18 -3
  38. secator/tasks/naabu.py +15 -1
  39. secator/tasks/nmap.py +32 -20
  40. secator/tasks/nuclei.py +4 -1
  41. secator/tasks/searchsploit.py +9 -2
  42. secator/tasks/wpscan.py +12 -1
  43. secator/template.py +1 -1
  44. secator/utils.py +151 -62
  45. {secator-0.7.0.dist-info → secator-0.8.0.dist-info}/METADATA +50 -45
  46. {secator-0.7.0.dist-info → secator-0.8.0.dist-info}/RECORD +49 -49
  47. {secator-0.7.0.dist-info → secator-0.8.0.dist-info}/WHEEL +1 -1
  48. {secator-0.7.0.dist-info → secator-0.8.0.dist-info}/entry_points.txt +0 -0
  49. {secator-0.7.0.dist-info → secator-0.8.0.dist-info}/licenses/LICENSE +0 -0
secator/utils.py CHANGED
@@ -26,7 +26,7 @@ import ifaddr
26
26
  import yaml
27
27
 
28
28
  from secator.definitions import (DEBUG_COMPONENT, VERSION, DEV_PACKAGE)
29
- from secator.config import CONFIG, ROOT_FOLDER, LIB_FOLDER
29
+ from secator.config import CONFIG, ROOT_FOLDER, LIB_FOLDER, download_file
30
30
  from secator.rich import console
31
31
 
32
32
  logger = logging.getLogger(__name__)
@@ -308,11 +308,21 @@ def pluralize(word):
308
308
  """
309
309
  if word.endswith('y'):
310
310
  return word.rstrip('y') + 'ies'
311
- else:
312
- return f'{word}s'
311
+ return f'{word}s'
313
312
 
314
313
 
315
314
  def load_fixture(name, fixtures_dir, ext=None, only_path=False):
315
+ """Load fixture a fixture dir. Optionally load it's content if it's JSON / YAML.
316
+
317
+ Args:
318
+ name (str): Fixture name.
319
+ fixtures_dir (str): Fixture parent directory.
320
+ ext (str, Optional): Extension to load.
321
+ only_path (bool, Optional): Return fixture path instead of fixture content.
322
+
323
+ Returns:
324
+ str: Fixture path or content.
325
+ """
316
326
  fixture_path = f'{fixtures_dir}/{name}'
317
327
  exts = ['.json', '.txt', '.xml', '.rc']
318
328
  if ext:
@@ -331,10 +341,19 @@ def load_fixture(name, fixtures_dir, ext=None, only_path=False):
331
341
 
332
342
 
333
343
  def get_file_timestamp():
344
+ """Get current timestamp into a formatted string."""
334
345
  return datetime.now().strftime("%Y_%m_%d-%I_%M_%S_%f_%p")
335
346
 
336
347
 
337
348
  def detect_host(interface=None):
349
+ """Detect hostname from ethernet adapters.
350
+
351
+ Args:
352
+ interface (str): Interface name to get hostname from.
353
+
354
+ Returns:
355
+ str | None: hostname or ip address, or None if not found.
356
+ """
338
357
  adapters = ifaddr.get_adapters()
339
358
  for adapter in adapters:
340
359
  iface = adapter.name
@@ -345,7 +364,14 @@ def detect_host(interface=None):
345
364
 
346
365
 
347
366
  def rich_to_ansi(text):
348
- """Convert text formatted with rich markup to standard string."""
367
+ """Convert text formatted with rich markup to standard string.
368
+
369
+ Args:
370
+ text (str): Text.
371
+
372
+ Returns:
373
+ str: Converted text (ANSI).
374
+ """
349
375
  from rich.console import Console
350
376
  tmp_console = Console(file=None, highlight=False, color_system='truecolor')
351
377
  with tmp_console.capture() as capture:
@@ -353,43 +379,65 @@ def rich_to_ansi(text):
353
379
  return capture.get()
354
380
 
355
381
 
382
+ def rich_escape(obj):
383
+ """Escape object for rich printing.
384
+
385
+ Args:
386
+ obj (any): Input object.
387
+
388
+ Returns:
389
+ any: Initial object, or escaped Rich string.
390
+ """
391
+ if isinstance(obj, str):
392
+ return obj.replace('[', r'\[').replace(']', r'\]')
393
+ return obj
394
+
395
+
356
396
  def format_object(obj, obj_breaklines=False):
357
- """Format the debug object for printing."""
358
- sep = '\n ' if obj_breaklines else ', '
359
- if isinstance(obj, dict):
360
- return sep.join(f'[dim cyan]{k}[/] [dim yellow]->[/] [dim green]{v}[/]' for k, v in obj.items() if v is not None) # noqa: E501
361
- elif isinstance(obj, list):
362
- return f'[dim green]{sep.join(obj)}[/]'
363
- return ''
397
+ """Format the debug object for printing.
398
+
399
+ Args:
400
+ obj (dict | list): Input object.
401
+ obj_breaklines (bool): Split output with newlines for each item in input object.
402
+
403
+ Returns:
404
+ str: Rich-formatted string.
405
+ """
406
+ sep = '\n ' if obj_breaklines else ', '
407
+ if isinstance(obj, dict):
408
+ return sep.join(f'[dim cyan]{k}[/] [dim yellow]->[/] [dim green]{v}[/]' for k, v in obj.items() if v is not None) # noqa: E501
409
+ elif isinstance(obj, list):
410
+ return f'[dim green]{sep.join(obj)}[/]'
411
+ return ''
364
412
 
365
413
 
366
414
  def debug(msg, sub='', id='', obj=None, lazy=None, obj_after=True, obj_breaklines=False, verbose=False):
367
- """Print debug log if DEBUG >= level."""
368
- if not DEBUG_COMPONENT or DEBUG_COMPONENT == [""]:
369
- return
415
+ """Print debug log if DEBUG >= level."""
416
+ if not DEBUG_COMPONENT or DEBUG_COMPONENT == [""]:
417
+ return
370
418
 
371
- if sub:
372
- if verbose and sub not in DEBUG_COMPONENT:
373
- sub = f'debug.{sub}'
374
- if not any(sub.startswith(s) for s in DEBUG_COMPONENT):
375
- return
419
+ if sub:
420
+ if verbose and sub not in DEBUG_COMPONENT:
421
+ sub = f'debug.{sub}'
422
+ if not any(sub.startswith(s) for s in DEBUG_COMPONENT):
423
+ return
376
424
 
377
- if lazy:
378
- msg = lazy(msg)
425
+ if lazy:
426
+ msg = lazy(msg)
379
427
 
380
- formatted_msg = f'[dim yellow4]{sub:13s}[/] ' if sub else ''
381
- obj_str = format_object(obj, obj_breaklines) if obj else ''
428
+ formatted_msg = f'[yellow4]{sub:13s}[/] ' if sub else ''
429
+ obj_str = format_object(obj, obj_breaklines) if obj else ''
382
430
 
383
- # Constructing the message string based on object position
384
- if obj_str and not obj_after:
385
- formatted_msg += f'{obj_str} '
386
- formatted_msg += f'[dim yellow]{msg}[/]'
387
- if obj_str and obj_after:
388
- formatted_msg += f': {obj_str}'
389
- if id:
390
- formatted_msg += f' [italic dim gray11]\[{id}][/]'
431
+ # Constructing the message string based on object position
432
+ if obj_str and not obj_after:
433
+ formatted_msg += f'{obj_str} '
434
+ formatted_msg += f'[yellow]{msg}[/]'
435
+ if obj_str and obj_after:
436
+ formatted_msg += f': {obj_str}'
437
+ if id:
438
+ formatted_msg += rf' [italic gray11]\[{id}][/]'
391
439
 
392
- console.print(f'[dim red]🐛 {formatted_msg}[/]', style='red')
440
+ console.print(rf'[dim]\[[magenta4]DBG[/]] {formatted_msg}[/]')
393
441
 
394
442
 
395
443
  def escape_mongodb_url(url):
@@ -414,7 +462,7 @@ def print_version():
414
462
  """Print secator version information."""
415
463
  from secator.installer import get_version_info
416
464
  console.print(f'[bold gold3]Current version[/]: {VERSION}', highlight=False, end='')
417
- info = get_version_info('secator', github_handle='freelabz/secator', version=VERSION)
465
+ info = get_version_info('secator', install_github_handle='freelabz/secator', version=VERSION)
418
466
  latest_version = info['latest_version']
419
467
  status = info['status']
420
468
  location = info['location']
@@ -528,16 +576,15 @@ def get_file_date(file_path):
528
576
 
529
577
 
530
578
  def trim_string(s, max_length=30):
531
- """
532
- Trims a long string to include the beginning and the end, with an ellipsis in the middle.
533
- The output string will not exceed the specified maximum length.
579
+ """Trims a long string to include the beginning and the end, with an ellipsis in the middle. The output string will
580
+ not exceed the specified maximum length.
534
581
 
535
582
  Args:
536
583
  s (str): The string to be trimmed.
537
584
  max_length (int): The maximum allowed length of the trimmed string.
538
585
 
539
586
  Returns:
540
- str: The trimmed string.
587
+ str: The trimmed string.
541
588
  """
542
589
  if len(s) <= max_length:
543
590
  return s # Return the original string if it's short enough
@@ -627,6 +674,14 @@ def list_reports(workspace=None, type=None, timedelta=None):
627
674
 
628
675
 
629
676
  def get_info_from_report_path(path):
677
+ """Get some info from the report path, like workspace, run type and id.
678
+
679
+ Args:
680
+ path (pathlib.Path): Report path.
681
+
682
+ Returns:
683
+ dict: Info dict.
684
+ """
630
685
  try:
631
686
  ws, runner_type, number = path.parts[-4], path.parts[-3], path.parts[-2]
632
687
  workspace_path = '/'.join(path.parts[:-3])
@@ -641,6 +696,14 @@ def get_info_from_report_path(path):
641
696
 
642
697
 
643
698
  def human_to_timedelta(time_str):
699
+ """Convert human time to a timedelta object.
700
+
701
+ Args:
702
+ str: Time string in human format (like 2 years)
703
+
704
+ Returns:
705
+ datetime.TimeDelta: TimeDelta object.
706
+ """
644
707
  if not time_str:
645
708
  return None
646
709
  parts = TIMEDELTA_REGEX.match(time_str)
@@ -661,31 +724,57 @@ def human_to_timedelta(time_str):
661
724
 
662
725
 
663
726
  def deep_merge_dicts(*dicts):
664
- """
665
- Recursively merges multiple dictionaries by concatenating lists and merging nested dictionaries.
727
+ """Recursively merges multiple dictionaries by concatenating lists and merging nested dictionaries.
728
+
729
+ Args:
730
+ dicts (tuple): A tuple of dictionary objects to merge.
731
+
732
+ Returns:
733
+ dict: A new dictionary containing merged keys and values from all input dictionaries.
734
+ """
735
+ def merge_two_dicts(dict1, dict2):
736
+ """Helper function that merges two dictionaries.
737
+
738
+ Args:
739
+ dict1 (dict): First dict.
740
+ dict2 (dict): Second dict.
741
+ Returns:
742
+ dict: Merged dict.
743
+ """
744
+ result = dict(dict1) # Create a copy of dict1 to avoid modifying it.
745
+ for key, value in dict2.items():
746
+ if key in result:
747
+ if isinstance(result[key], dict) and isinstance(value, dict):
748
+ result[key] = merge_two_dicts(result[key], value)
749
+ elif isinstance(result[key], list) and isinstance(value, list):
750
+ result[key] += value # Concatenating lists
751
+ else:
752
+ result[key] = value # Overwrite if not both lists or both dicts
753
+ else:
754
+ result[key] = value
755
+ return result
756
+
757
+ # Use reduce to apply merge_two_dicts to all dictionaries in dicts
758
+ return reduce(merge_two_dicts, dicts, {})
666
759
 
667
- Args:
668
- dicts (tuple): A tuple of dictionary objects to merge.
669
760
 
670
- Returns:
671
- dict: A new dictionary containing merged keys and values from all input dictionaries.
761
+ def process_wordlist(val):
762
+ """Pre-process wordlist option value to allow referencing wordlists from remote URLs or from config keys.
763
+
764
+ Args:
765
+ val (str): Can be a config value in CONFIG.wordlists.defaults or CONFIG.wordlists.templates, or a local path,
766
+ or a URL.
672
767
  """
673
- def merge_two_dicts(dict1, dict2):
674
- """
675
- Helper function that merges two dictionaries.
676
- """
677
- result = dict(dict1) # Create a copy of dict1 to avoid modifying it.
678
- for key, value in dict2.items():
679
- if key in result:
680
- if isinstance(result[key], dict) and isinstance(value, dict):
681
- result[key] = merge_two_dicts(result[key], value)
682
- elif isinstance(result[key], list) and isinstance(value, list):
683
- result[key] += value # Concatenating lists
684
- else:
685
- result[key] = value # Overwrite if not both lists or both dicts
686
- else:
687
- result[key] = value
688
- return result
689
-
690
- # Use reduce to apply merge_two_dicts to all dictionaries in dicts
691
- return reduce(merge_two_dicts, dicts, {})
768
+ default_wordlist = getattr(CONFIG.wordlists.defaults, val)
769
+ if default_wordlist:
770
+ val = default_wordlist
771
+ template_wordlist = getattr(CONFIG.wordlists.templates, val)
772
+ if template_wordlist:
773
+ return template_wordlist
774
+ else:
775
+ return download_file(
776
+ val,
777
+ target_folder=CONFIG.dirs.wordlists,
778
+ offline_mode=CONFIG.offline_mode,
779
+ type='wordlist'
780
+ )
@@ -1,10 +1,11 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: secator
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: The pentester's swiss knife.
5
5
  Project-URL: Homepage, https://github.com/freelabz/secator
6
6
  Project-URL: Issues, https://github.com/freelabz/secator/issues
7
7
  Author-email: FreeLabz <sales@freelabz.com>
8
+ License-File: LICENSE
8
9
  Keywords: automation,cybersecurity,pentest,recon,vulnerability
9
10
  Classifier: Development Status :: 3 - Alpha
10
11
  Classifier: Intended Audience :: Developers
@@ -21,6 +22,7 @@ Requires-Python: >=3.8
21
22
  Requires-Dist: beautifulsoup4<=5
22
23
  Requires-Dist: celery<6
23
24
  Requires-Dist: cpe<2
25
+ Requires-Dist: distro<2
24
26
  Requires-Dist: dotmap<2
25
27
  Requires-Dist: free-proxy<2
26
28
  Requires-Dist: furl<3
@@ -68,7 +70,7 @@ Requires-Dist: gevent<25; extra == 'worker'
68
70
  Description-Content-Type: text/markdown
69
71
 
70
72
  <h1 align="center">
71
- <img src="https://github.com/freelabz/secator/assets/9629314/ee203af4-e853-439a-af01-edeabfc4bf07/" width="400">
73
+ <img src="https://github.com/freelabz/secator/assets/9629314/ee203af4-e853-439a-af01-edeabfc4bf07/" width="400">
72
74
  </h1>
73
75
 
74
76
  <h4 align="center">The pentester's swiss knife.</h4>
@@ -119,32 +121,35 @@ and it is designed to improve productivity for pentesters and security researche
119
121
 
120
122
  `secator` integrates the following tools:
121
123
 
122
- | Name | Description | Category |
123
- |---------------------------------------------------------------|--------------------------------------------------------------------------------|----------------|
124
- | [httpx](https://github.com/projectdiscovery/httpx) | Fast HTTP prober. | `http` |
125
- | [cariddi](https://github.com/edoardottt/cariddi) | Fast crawler and endpoint secrets / api keys / tokens matcher. | `http/crawler` |
126
- | [gau](https://github.com/lc/gau) | Offline URL crawler (Alien Vault, The Wayback Machine, Common Crawl, URLScan). | `http/crawler` |
127
- | [gospider](https://github.com/jaeles-project/gospider) | Fast web spider written in Go. | `http/crawler` |
128
- | [katana](https://github.com/projectdiscovery/katana) | Next-generation crawling and spidering framework. | `http/crawler` |
129
- | [dirsearch](https://github.com/maurosoria/dirsearch) | Web path discovery. | `http/fuzzer` |
130
- | [feroxbuster](https://github.com/epi052/feroxbuster) | Simple, fast, recursive content discovery tool written in Rust. | `http/fuzzer` |
131
- | [ffuf](https://github.com/ffuf/ffuf) | Fast web fuzzer written in Go. | `http/fuzzer` |
132
- | [h8mail](https://github.com/khast3x/h8mail) | Email OSINT and breach hunting tool. | `osint` |
133
- | [dnsx](https://github.com/projectdiscovery/dnsx) | Fast and multi-purpose DNS toolkit designed for running DNS queries. | `recon/dns` |
134
- | [dnsxbrute](https://github.com/projectdiscovery/dnsx) | Fast and multi-purpose DNS toolkit designed for running DNS queries (bruteforce mode). | `recon/dns` |
135
- | [subfinder](https://github.com/projectdiscovery/subfinder) | Fast subdomain finder. | `recon/dns` |
136
- | [fping](https://fping.org/) | Find alive hosts on local networks. | `recon/ip` |
137
- | [mapcidr](https://github.com/projectdiscovery/mapcidr) | Expand CIDR ranges into IPs. | `recon/ip` |
138
- | [naabu](https://github.com/projectdiscovery/naabu) | Fast port discovery tool. | `recon/port` |
139
- | [maigret](https://github.com/soxoj/maigret) | Hunt for user accounts across many websites. | `recon/user` |
140
- | [gf](https://github.com/tomnomnom/gf) | A wrapper around grep to avoid typing common patterns. | `tagger` |
141
- | [grype](https://github.com/anchore/grype) | A vulnerability scanner for container images and filesystems. | `vuln/code` |
142
- | [dalfox](https://github.com/hahwul/dalfox) | Powerful XSS scanning tool and parameter analyzer. | `vuln/http` |
143
- | [msfconsole](https://docs.rapid7.com/metasploit/msf-overview) | CLI to access and work with the Metasploit Framework. | `vuln/http` |
144
- | [wpscan](https://github.com/wpscanteam/wpscan) | WordPress Security Scanner | `vuln/multi` |
145
- | [nmap](https://github.com/nmap/nmap) | Vulnerability scanner using NSE scripts. | `vuln/multi` |
146
- | [nuclei](https://github.com/projectdiscovery/nuclei) | Fast and customisable vulnerability scanner based on simple YAML based DSL. | `vuln/multi` |
147
- | [searchsploit](https://gitlab.com/exploit-database/exploitdb) | Exploit searcher. | `exploit/search` |
124
+ | Name | Description | Category |
125
+ |---------------------------------------------------------------|--------------------------------------------------------------------------------|-----------------|
126
+ | [httpx](https://github.com/projectdiscovery/httpx) | Fast HTTP prober. | `http` |
127
+ | [cariddi](https://github.com/edoardottt/cariddi) | Fast crawler and endpoint secrets / api keys / tokens matcher. | `http/crawler` |
128
+ | [gau](https://github.com/lc/gau) | Offline URL crawler (Alien Vault, The Wayback Machine, Common Crawl, URLScan). | `http/crawler` |
129
+ | [gospider](https://github.com/jaeles-project/gospider) | Fast web spider written in Go. | `http/crawler` |
130
+ | [katana](https://github.com/projectdiscovery/katana) | Next-generation crawling and spidering framework. | `http/crawler` |
131
+ | [dirsearch](https://github.com/maurosoria/dirsearch) | Web path discovery. | `http/fuzzer` |
132
+ | [feroxbuster](https://github.com/epi052/feroxbuster) | Simple, fast, recursive content discovery tool written in Rust. | `http/fuzzer` |
133
+ | [ffuf](https://github.com/ffuf/ffuf) | Fast web fuzzer written in Go. | `http/fuzzer` |
134
+ | [h8mail](https://github.com/khast3x/h8mail) | Email OSINT and breach hunting tool. | `osint` |
135
+ | [dnsx](https://github.com/projectdiscovery/dnsx) | Fast and multi-purpose DNS toolkit. | `recon/dns` |
136
+ | [dnsxbrute](https://github.com/projectdiscovery/dnsx) | Fast and multi-purpose DNS toolkit (bruteforce mode). | `recon/dns` |
137
+ | [subfinder](https://github.com/projectdiscovery/subfinder) | Fast subdomain finder. | `recon/dns` |
138
+ | [fping](https://fping.org/) | Find alive hosts on local networks. | `recon/ip` |
139
+ | [mapcidr](https://github.com/projectdiscovery/mapcidr) | Expand CIDR ranges into IPs. | `recon/ip` |
140
+ | [naabu](https://github.com/projectdiscovery/naabu) | Fast port discovery tool. | `recon/port` |
141
+ | [maigret](https://github.com/soxoj/maigret) | Hunt for user accounts across many websites. | `recon/user` |
142
+ | [gf](https://github.com/tomnomnom/gf) | A wrapper around grep to avoid typing common patterns. | `tagger` |
143
+ | [grype](https://github.com/anchore/grype) | A vulnerability scanner for container images and filesystems. | `vuln/code` |
144
+ | [dalfox](https://github.com/hahwul/dalfox) | Powerful XSS scanning tool and parameter analyzer. | `vuln/http` |
145
+ | [msfconsole](https://docs.rapid7.com/metasploit/msf-overview) | CLI to access and work with the Metasploit Framework. | `vuln/http` |
146
+ | [wpscan](https://github.com/wpscanteam/wpscan) | WordPress Security Scanner | `vuln/multi` |
147
+ | [nmap](https://github.com/nmap/nmap) | Vulnerability scanner using NSE scripts. | `vuln/multi` |
148
+ | [nuclei](https://github.com/projectdiscovery/nuclei) | Fast and customisable vulnerability scanner based on simple YAML based DSL. | `vuln/multi` |
149
+ | [bbot](https://github.com/blacklanternsecurity/bbot) | Multipurpose scanner. | `multi` |
150
+ | [searchsploit](https://gitlab.com/exploit-database/exploitdb) | Exploit searcher based on ExploitDB. | `exploit/search`|
151
+ | [bup](https://github.com/laluka/bypass-url-parser) | 40X bypasser. | `http` |
152
+
148
153
 
149
154
  Feel free to request new tools to be added by opening an issue, but please
150
155
  check that the tool complies with our selection criterias before doing so. If it doesn't but you still want to integrate it into `secator`, you can plug it in (see the [dev guide](https://docs.freelabz.com/for-developers/writing-custom-tasks)).
@@ -155,7 +160,7 @@ check that the tool complies with our selection criterias before doing so. If it
155
160
  ### Installing secator
156
161
 
157
162
  <details>
158
- <summary>Pipx</summary>
163
+ <summary>Pipx</summary>
159
164
 
160
165
  ```sh
161
166
  pipx install secator
@@ -164,7 +169,7 @@ pipx install secator
164
169
  </details>
165
170
 
166
171
  <details>
167
- <summary>Pip</summary>
172
+ <summary>Pip</summary>
168
173
 
169
174
  ```sh
170
175
  pip install secator
@@ -182,7 +187,7 @@ wget -O - https://raw.githubusercontent.com/freelabz/secator/main/scripts/instal
182
187
  </details>
183
188
 
184
189
  <details>
185
- <summary>Docker</summary>
190
+ <summary>Docker</summary>
186
191
 
187
192
  ```sh
188
193
  docker run -it --rm --net=host -v ~/.secator:/root/.secator freelabz/secator --help
@@ -203,13 +208,13 @@ secator --help
203
208
  </details>
204
209
 
205
210
  <details>
206
- <summary>Docker Compose</summary>
211
+ <summary>Docker Compose</summary>
207
212
 
208
213
  ```sh
209
214
  git clone https://github.com/freelabz/secator
210
215
  cd secator
211
216
  docker-compose up -d
212
- docker-compose exec secator secator --help
217
+ docker-compose exec secator-client secator --help
213
218
  ```
214
219
 
215
220
  </details>
@@ -223,7 +228,7 @@ docker-compose exec secator secator --help
223
228
  We provide utilities to install required languages if you don't manage them externally:
224
229
 
225
230
  <details>
226
- <summary>Go</summary>
231
+ <summary>Go</summary>
227
232
 
228
233
  ```sh
229
234
  secator install langs go
@@ -232,7 +237,7 @@ secator install langs go
232
237
  </details>
233
238
 
234
239
  <details>
235
- <summary>Ruby</summary>
240
+ <summary>Ruby</summary>
236
241
 
237
242
  ```sh
238
243
  secator install langs ruby
@@ -247,7 +252,7 @@ secator install langs ruby
247
252
  We provide utilities to install or update each supported tool which should work on all systems supporting `apt`:
248
253
 
249
254
  <details>
250
- <summary>All tools</summary>
255
+ <summary>All tools</summary>
251
256
 
252
257
  ```sh
253
258
  secator install tools
@@ -256,7 +261,7 @@ secator install tools
256
261
  </details>
257
262
 
258
263
  <details>
259
- <summary>Specific tools</summary>
264
+ <summary>Specific tools</summary>
260
265
 
261
266
  ```sh
262
267
  secator install tools <TOOL_NAME>
@@ -279,7 +284,7 @@ Please make sure you are using the latest available versions for each tool befor
279
284
  There are several addons available for `secator`:
280
285
 
281
286
  <details>
282
- <summary>worker</summary>
287
+ <summary>worker</summary>
283
288
 
284
289
  Add support for Celery workers (see [Distributed runs with Celery](https://docs.freelabz.com/in-depth/distributed-runs-with-celery)).
285
290
  ```sh
@@ -290,7 +295,7 @@ secator install addons worker
290
295
 
291
296
 
292
297
  <details>
293
- <summary>google</summary>
298
+ <summary>google</summary>
294
299
 
295
300
  Add support for Google Drive exporter (`-o gdrive`).
296
301
 
@@ -301,7 +306,7 @@ secator install addons google
301
306
  </details>
302
307
 
303
308
  <details>
304
- <summary>mongodb</summary>
309
+ <summary>mongodb</summary>
305
310
 
306
311
  Add support for MongoDB driver (`-driver mongodb`).
307
312
  ```sh
@@ -311,7 +316,7 @@ secator install addons mongodb
311
316
  </details>
312
317
 
313
318
  <details>
314
- <summary>redis</summary>
319
+ <summary>redis</summary>
315
320
 
316
321
  Add support for Redis backend (Celery).
317
322
 
@@ -322,7 +327,7 @@ secator install addons redis
322
327
  </details>
323
328
 
324
329
  <details>
325
- <summary>dev</summary>
330
+ <summary>dev</summary>
326
331
 
327
332
  Add development tools like `coverage` and `flake8` required for running tests.
328
333
 
@@ -333,7 +338,7 @@ secator install addons dev
333
338
  </details>
334
339
 
335
340
  <details>
336
- <summary>trace</summary>
341
+ <summary>trace</summary>
337
342
 
338
343
  Add tracing tools like `memray` and `pyinstrument` required for tracing functions.
339
344
 
@@ -344,7 +349,7 @@ secator install addons trace
344
349
  </details>
345
350
 
346
351
  <details>
347
- <summary>build</summary>
352
+ <summary>build</summary>
348
353
 
349
354
  Add `hatch` for building and publishing the PyPI package.
350
355