secator 0.11.1__tar.gz → 0.13.0__tar.gz

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

Potentially problematic release.


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

Files changed (200) hide show
  1. {secator-0.11.1 → secator-0.13.0}/.docker/Dockerfile.alpine +2 -0
  2. {secator-0.11.1 → secator-0.13.0}/.docker/Dockerfile.arch +2 -2
  3. {secator-0.11.1 → secator-0.13.0}/.docker/Dockerfile.debian +2 -2
  4. {secator-0.11.1 → secator-0.13.0}/.docker/Dockerfile.kali +2 -2
  5. {secator-0.11.1 → secator-0.13.0}/.docker/Dockerfile.osx +2 -2
  6. {secator-0.11.1 → secator-0.13.0}/.docker/Dockerfile.ubuntu +2 -2
  7. {secator-0.11.1 → secator-0.13.0}/CHANGELOG.md +27 -0
  8. {secator-0.11.1 → secator-0.13.0}/PKG-INFO +1 -1
  9. {secator-0.11.1 → secator-0.13.0}/pyproject.toml +1 -1
  10. {secator-0.11.1 → secator-0.13.0}/secator/cli.py +175 -66
  11. {secator-0.11.1 → secator-0.13.0}/secator/config.py +1 -0
  12. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/host_recon.yaml +11 -2
  13. secator-0.13.0/secator/configs/workflows/port_scan.yaml +39 -0
  14. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/url_dirsearch.yaml +5 -0
  15. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/url_params_fuzz.yaml +2 -0
  16. {secator-0.11.1 → secator-0.13.0}/secator/decorators.py +39 -21
  17. {secator-0.11.1 → secator-0.13.0}/secator/definitions.py +0 -4
  18. {secator-0.11.1 → secator-0.13.0}/secator/installer.py +29 -15
  19. {secator-0.11.1 → secator-0.13.0}/secator/runners/_base.py +2 -1
  20. {secator-0.11.1 → secator-0.13.0}/secator/runners/_helpers.py +13 -2
  21. {secator-0.11.1 → secator-0.13.0}/secator/runners/command.py +3 -1
  22. {secator-0.11.1 → secator-0.13.0}/secator/tasks/_categories.py +2 -2
  23. {secator-0.11.1 → secator-0.13.0}/secator/tasks/arjun.py +11 -2
  24. {secator-0.11.1 → secator-0.13.0}/secator/tasks/bbot.py +30 -4
  25. {secator-0.11.1 → secator-0.13.0}/secator/tasks/bup.py +2 -1
  26. {secator-0.11.1 → secator-0.13.0}/secator/tasks/cariddi.py +15 -3
  27. {secator-0.11.1 → secator-0.13.0}/secator/tasks/dalfox.py +2 -1
  28. {secator-0.11.1 → secator-0.13.0}/secator/tasks/dirsearch.py +1 -1
  29. {secator-0.11.1 → secator-0.13.0}/secator/tasks/dnsx.py +2 -1
  30. {secator-0.11.1 → secator-0.13.0}/secator/tasks/dnsxbrute.py +2 -1
  31. {secator-0.11.1 → secator-0.13.0}/secator/tasks/feroxbuster.py +3 -2
  32. {secator-0.11.1 → secator-0.13.0}/secator/tasks/ffuf.py +2 -1
  33. {secator-0.11.1 → secator-0.13.0}/secator/tasks/gau.py +2 -1
  34. {secator-0.11.1 → secator-0.13.0}/secator/tasks/gitleaks.py +4 -3
  35. {secator-0.11.1 → secator-0.13.0}/secator/tasks/gospider.py +3 -2
  36. {secator-0.11.1 → secator-0.13.0}/secator/tasks/grype.py +1 -0
  37. {secator-0.11.1 → secator-0.13.0}/secator/tasks/h8mail.py +2 -1
  38. {secator-0.11.1 → secator-0.13.0}/secator/tasks/httpx.py +3 -2
  39. {secator-0.11.1 → secator-0.13.0}/secator/tasks/katana.py +4 -3
  40. {secator-0.11.1 → secator-0.13.0}/secator/tasks/maigret.py +1 -1
  41. {secator-0.11.1 → secator-0.13.0}/secator/tasks/mapcidr.py +2 -1
  42. {secator-0.11.1 → secator-0.13.0}/secator/tasks/msfconsole.py +4 -3
  43. {secator-0.11.1 → secator-0.13.0}/secator/tasks/naabu.py +4 -2
  44. {secator-0.11.1 → secator-0.13.0}/secator/tasks/nuclei.py +15 -9
  45. {secator-0.11.1 → secator-0.13.0}/secator/tasks/searchsploit.py +3 -2
  46. {secator-0.11.1 → secator-0.13.0}/secator/tasks/subfinder.py +2 -1
  47. {secator-0.11.1 → secator-0.13.0}/secator/tasks/testssl.py +4 -3
  48. {secator-0.11.1 → secator-0.13.0}/secator/tasks/trivy.py +2 -2
  49. {secator-0.11.1 → secator-0.13.0}/secator/tasks/wafw00f.py +2 -1
  50. {secator-0.11.1 → secator-0.13.0}/secator/tasks/wpprobe.py +2 -1
  51. {secator-0.11.1 → secator-0.13.0}/secator/tasks/wpscan.py +6 -3
  52. {secator-0.11.1 → secator-0.13.0}/secator/template.py +12 -0
  53. {secator-0.11.1 → secator-0.13.0}/tests/integration/test_tasks.py +8 -1
  54. {secator-0.11.1 → secator-0.13.0}/.docker/build_all.sh +0 -0
  55. {secator-0.11.1 → secator-0.13.0}/.dockerignore +0 -0
  56. {secator-0.11.1 → secator-0.13.0}/.flake8 +0 -0
  57. {secator-0.11.1 → secator-0.13.0}/.gitignore +0 -0
  58. {secator-0.11.1 → secator-0.13.0}/CONTRIBUTING.md +0 -0
  59. {secator-0.11.1 → secator-0.13.0}/Dockerfile +0 -0
  60. {secator-0.11.1 → secator-0.13.0}/LICENSE +0 -0
  61. {secator-0.11.1 → secator-0.13.0}/README.md +0 -0
  62. {secator-0.11.1 → secator-0.13.0}/SECURITY.md +0 -0
  63. {secator-0.11.1 → secator-0.13.0}/cloudbuild.yaml +0 -0
  64. {secator-0.11.1 → secator-0.13.0}/helm/.helmignore +0 -0
  65. {secator-0.11.1 → secator-0.13.0}/helm/Chart.yaml +0 -0
  66. {secator-0.11.1 → secator-0.13.0}/helm/templates/redis-service.yaml +0 -0
  67. {secator-0.11.1 → secator-0.13.0}/helm/templates/redis.yaml +0 -0
  68. {secator-0.11.1 → secator-0.13.0}/helm/templates/secator-manager.yaml +0 -0
  69. {secator-0.11.1 → secator-0.13.0}/helm/templates/secator-worker.yaml +0 -0
  70. {secator-0.11.1 → secator-0.13.0}/helm/values.yaml +0 -0
  71. {secator-0.11.1 → secator-0.13.0}/scripts/download_cves.sh +0 -0
  72. {secator-0.11.1 → secator-0.13.0}/scripts/install.sh +0 -0
  73. {secator-0.11.1 → secator-0.13.0}/scripts/install_asciinema.sh +0 -0
  74. {secator-0.11.1 → secator-0.13.0}/scripts/install_go.sh +0 -0
  75. {secator-0.11.1 → secator-0.13.0}/scripts/install_ruby.sh +0 -0
  76. {secator-0.11.1 → secator-0.13.0}/scripts/msf/exploit_cve.rc +0 -0
  77. {secator-0.11.1 → secator-0.13.0}/scripts/msf/ftp_anonymous.rc +0 -0
  78. {secator-0.11.1 → secator-0.13.0}/scripts/msf/ftp_version.rc +0 -0
  79. {secator-0.11.1 → secator-0.13.0}/scripts/msf/ftp_vsftpd_234_backdoor.rc +0 -0
  80. {secator-0.11.1 → secator-0.13.0}/scripts/msf/redis.rc +0 -0
  81. {secator-0.11.1 → secator-0.13.0}/scripts/stories/STORY.md +0 -0
  82. {secator-0.11.1 → secator-0.13.0}/scripts/stories/aliases.sh +0 -0
  83. {secator-0.11.1 → secator-0.13.0}/scripts/stories/demo.sh +0 -0
  84. {secator-0.11.1 → secator-0.13.0}/scripts/stories/fmt.sh +0 -0
  85. {secator-0.11.1 → secator-0.13.0}/scripts/stories/input.sh +0 -0
  86. {secator-0.11.1 → secator-0.13.0}/scripts/stories/pipe.sh +0 -0
  87. {secator-0.11.1 → secator-0.13.0}/scripts/stories/short_demo.sh +0 -0
  88. {secator-0.11.1 → secator-0.13.0}/secator/.gitignore +0 -0
  89. {secator-0.11.1 → secator-0.13.0}/secator/__init__.py +0 -0
  90. {secator-0.11.1 → secator-0.13.0}/secator/celery.py +0 -0
  91. {secator-0.11.1 → secator-0.13.0}/secator/celery_signals.py +0 -0
  92. {secator-0.11.1 → secator-0.13.0}/secator/celery_utils.py +0 -0
  93. {secator-0.11.1 → secator-0.13.0}/secator/configs/__init__.py +0 -0
  94. {secator-0.11.1 → secator-0.13.0}/secator/configs/profiles/__init__.py +0 -0
  95. {secator-0.11.1 → secator-0.13.0}/secator/configs/profiles/aggressive.yaml +0 -0
  96. {secator-0.11.1 → secator-0.13.0}/secator/configs/profiles/default.yaml +0 -0
  97. {secator-0.11.1 → secator-0.13.0}/secator/configs/profiles/stealth.yaml +0 -0
  98. {secator-0.11.1 → secator-0.13.0}/secator/configs/scans/__init__.py +0 -0
  99. {secator-0.11.1 → secator-0.13.0}/secator/configs/scans/domain.yaml +0 -0
  100. {secator-0.11.1 → secator-0.13.0}/secator/configs/scans/host.yaml +0 -0
  101. {secator-0.11.1 → secator-0.13.0}/secator/configs/scans/network.yaml +0 -0
  102. {secator-0.11.1 → secator-0.13.0}/secator/configs/scans/subdomain.yaml +0 -0
  103. {secator-0.11.1 → secator-0.13.0}/secator/configs/scans/url.yaml +0 -0
  104. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/__init__.py +0 -0
  105. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/cidr_recon.yaml +0 -0
  106. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/code_scan.yaml +0 -0
  107. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/subdomain_recon.yaml +0 -0
  108. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/url_bypass.yaml +0 -0
  109. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/url_crawl.yaml +0 -0
  110. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/url_fuzz.yaml +0 -0
  111. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/url_nuclei.yaml +0 -0
  112. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/url_vuln.yaml +0 -0
  113. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/user_hunt.yaml +0 -0
  114. {secator-0.11.1 → secator-0.13.0}/secator/configs/workflows/wordpress.yaml +0 -0
  115. {secator-0.11.1 → secator-0.13.0}/secator/exporters/__init__.py +0 -0
  116. {secator-0.11.1 → secator-0.13.0}/secator/exporters/_base.py +0 -0
  117. {secator-0.11.1 → secator-0.13.0}/secator/exporters/console.py +0 -0
  118. {secator-0.11.1 → secator-0.13.0}/secator/exporters/csv.py +0 -0
  119. {secator-0.11.1 → secator-0.13.0}/secator/exporters/gdrive.py +0 -0
  120. {secator-0.11.1 → secator-0.13.0}/secator/exporters/json.py +0 -0
  121. {secator-0.11.1 → secator-0.13.0}/secator/exporters/table.py +0 -0
  122. {secator-0.11.1 → secator-0.13.0}/secator/exporters/txt.py +0 -0
  123. {secator-0.11.1 → secator-0.13.0}/secator/hooks/__init__.py +0 -0
  124. {secator-0.11.1 → secator-0.13.0}/secator/hooks/gcs.py +0 -0
  125. {secator-0.11.1 → secator-0.13.0}/secator/hooks/mongodb.py +0 -0
  126. {secator-0.11.1 → secator-0.13.0}/secator/output_types/__init__.py +0 -0
  127. {secator-0.11.1 → secator-0.13.0}/secator/output_types/_base.py +0 -0
  128. {secator-0.11.1 → secator-0.13.0}/secator/output_types/certificate.py +0 -0
  129. {secator-0.11.1 → secator-0.13.0}/secator/output_types/error.py +0 -0
  130. {secator-0.11.1 → secator-0.13.0}/secator/output_types/exploit.py +0 -0
  131. {secator-0.11.1 → secator-0.13.0}/secator/output_types/info.py +0 -0
  132. {secator-0.11.1 → secator-0.13.0}/secator/output_types/ip.py +0 -0
  133. {secator-0.11.1 → secator-0.13.0}/secator/output_types/port.py +0 -0
  134. {secator-0.11.1 → secator-0.13.0}/secator/output_types/progress.py +0 -0
  135. {secator-0.11.1 → secator-0.13.0}/secator/output_types/record.py +0 -0
  136. {secator-0.11.1 → secator-0.13.0}/secator/output_types/stat.py +0 -0
  137. {secator-0.11.1 → secator-0.13.0}/secator/output_types/state.py +0 -0
  138. {secator-0.11.1 → secator-0.13.0}/secator/output_types/subdomain.py +0 -0
  139. {secator-0.11.1 → secator-0.13.0}/secator/output_types/tag.py +0 -0
  140. {secator-0.11.1 → secator-0.13.0}/secator/output_types/target.py +0 -0
  141. {secator-0.11.1 → secator-0.13.0}/secator/output_types/url.py +0 -0
  142. {secator-0.11.1 → secator-0.13.0}/secator/output_types/user_account.py +0 -0
  143. {secator-0.11.1 → secator-0.13.0}/secator/output_types/vulnerability.py +0 -0
  144. {secator-0.11.1 → secator-0.13.0}/secator/output_types/warning.py +0 -0
  145. {secator-0.11.1 → secator-0.13.0}/secator/report.py +0 -0
  146. {secator-0.11.1 → secator-0.13.0}/secator/rich.py +0 -0
  147. {secator-0.11.1 → secator-0.13.0}/secator/runners/__init__.py +0 -0
  148. {secator-0.11.1 → secator-0.13.0}/secator/runners/celery.py +0 -0
  149. {secator-0.11.1 → secator-0.13.0}/secator/runners/scan.py +0 -0
  150. {secator-0.11.1 → secator-0.13.0}/secator/runners/task.py +0 -0
  151. {secator-0.11.1 → secator-0.13.0}/secator/runners/workflow.py +0 -0
  152. {secator-0.11.1 → secator-0.13.0}/secator/scans/__init__.py +0 -0
  153. {secator-0.11.1 → secator-0.13.0}/secator/serializers/__init__.py +0 -0
  154. {secator-0.11.1 → secator-0.13.0}/secator/serializers/dataclass.py +0 -0
  155. {secator-0.11.1 → secator-0.13.0}/secator/serializers/json.py +0 -0
  156. {secator-0.11.1 → secator-0.13.0}/secator/serializers/regex.py +0 -0
  157. {secator-0.11.1 → secator-0.13.0}/secator/tasks/__init__.py +0 -0
  158. {secator-0.11.1 → secator-0.13.0}/secator/tasks/fping.py +0 -0
  159. {secator-0.11.1 → secator-0.13.0}/secator/tasks/gf.py +0 -0
  160. {secator-0.11.1 → secator-0.13.0}/secator/tasks/nmap.py +0 -0
  161. {secator-0.11.1 → secator-0.13.0}/secator/thread.py +0 -0
  162. {secator-0.11.1 → secator-0.13.0}/secator/utils.py +0 -0
  163. {secator-0.11.1 → secator-0.13.0}/secator/utils_test.py +0 -0
  164. {secator-0.11.1 → secator-0.13.0}/secator/workflows/__init__.py +0 -0
  165. {secator-0.11.1 → secator-0.13.0}/tests/__init__.py +0 -0
  166. {secator-0.11.1 → secator-0.13.0}/tests/fixtures/h8mail_breach.txt +0 -0
  167. {secator-0.11.1 → secator-0.13.0}/tests/fixtures/ls.py +0 -0
  168. {secator-0.11.1 → secator-0.13.0}/tests/fixtures/msfconsole_input.rc +0 -0
  169. {secator-0.11.1 → secator-0.13.0}/tests/fixtures/nmap_output.xml +0 -0
  170. {secator-0.11.1 → secator-0.13.0}/tests/integration/__init__.py +0 -0
  171. {secator-0.11.1 → secator-0.13.0}/tests/integration/inputs.py +0 -0
  172. {secator-0.11.1 → secator-0.13.0}/tests/integration/outputs.py +0 -0
  173. {secator-0.11.1 → secator-0.13.0}/tests/integration/setup.sh +0 -0
  174. {secator-0.11.1 → secator-0.13.0}/tests/integration/teardown.sh +0 -0
  175. {secator-0.11.1 → secator-0.13.0}/tests/integration/test_addons.py +0 -0
  176. {secator-0.11.1 → secator-0.13.0}/tests/integration/test_celery.py +0 -0
  177. {secator-0.11.1 → secator-0.13.0}/tests/integration/test_helpers.py +0 -0
  178. {secator-0.11.1 → secator-0.13.0}/tests/integration/test_scans.py +0 -0
  179. {secator-0.11.1 → secator-0.13.0}/tests/integration/test_worker.py +0 -0
  180. {secator-0.11.1 → secator-0.13.0}/tests/integration/test_workflows.py +0 -0
  181. {secator-0.11.1 → secator-0.13.0}/tests/integration/wordlist.txt +0 -0
  182. {secator-0.11.1 → secator-0.13.0}/tests/integration/wordlist_dns.txt +0 -0
  183. {secator-0.11.1 → secator-0.13.0}/tests/integration/wordpress_toolbox/Dockerfile +0 -0
  184. {secator-0.11.1 → secator-0.13.0}/tests/integration/wordpress_toolbox/Makefile +0 -0
  185. {secator-0.11.1 → secator-0.13.0}/tests/performance/__init__.py +0 -0
  186. {secator-0.11.1 → secator-0.13.0}/tests/performance/loadtester.py +0 -0
  187. {secator-0.11.1 → secator-0.13.0}/tests/performance/test_worker.py +0 -0
  188. {secator-0.11.1 → secator-0.13.0}/tests/unit/__init__.py +0 -0
  189. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_celery.py +0 -0
  190. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_cli.py +0 -0
  191. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_command.py +0 -0
  192. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_config.py +0 -0
  193. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_offline.py +0 -0
  194. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_runners.py +0 -0
  195. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_scans.py +0 -0
  196. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_serializers.py +0 -0
  197. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_tasks.py +0 -0
  198. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_tasks_categories.py +0 -0
  199. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_template.py +0 -0
  200. {secator-0.11.1 → secator-0.13.0}/tests/unit/test_utils.py +0 -0
@@ -21,6 +21,7 @@ RUN pipx install --pip-args="--no-cache-dir" . && \
21
21
 
22
22
  FROM python:3.12-alpine
23
23
  ARG flavor=full
24
+ ARG build_from_source=false
24
25
  ENV TERM="xterm-256color"
25
26
  ENV PATH="${PATH}:/root/.local/bin"
26
27
  ENV GOBIN="/root/.local/bin"
@@ -29,5 +30,6 @@ RUN apk add --no-cache \
29
30
  flock \
30
31
  pipx \
31
32
  sudo
33
+ RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
32
34
  RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
33
35
  ENTRYPOINT ["secator"]
@@ -31,6 +31,6 @@ RUN pipx install . && \
31
31
  secator install addons mongodb && \
32
32
  secator install addons redis && \
33
33
  secator install addons dev
34
- RUN secator config set security.force_source_install true
35
- RUN secator install tools --cleanup --fail-fast
34
+ RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
35
+ RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
36
36
  ENTRYPOINT ["secator"]
@@ -33,6 +33,6 @@ RUN pipx install . && \
33
33
  secator install addons redis && \
34
34
  secator install addons dev
35
35
  RUN secator install langs go
36
- RUN secator config set security.force_source_install true
37
- RUN secator install tools --cleanup --fail-fast
36
+ RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
37
+ RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
38
38
  ENTRYPOINT ["secator"]
@@ -32,6 +32,6 @@ RUN pipx install . && \
32
32
  secator install addons mongodb && \
33
33
  secator install addons redis && \
34
34
  secator install addons dev
35
- RUN secator config set security.force_source_install true
36
- RUN secator install tools --cleanup --fail-fast
35
+ RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
36
+ RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
37
37
  ENTRYPOINT ["secator"]
@@ -35,6 +35,6 @@ RUN pipx install . && \
35
35
  secator install addons mongodb && \
36
36
  secator install addons redis && \
37
37
  secator install addons dev
38
- RUN secator config set security.force_source_install true
39
- RUN secator install tools --cleanup --fail-fast
38
+ RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
39
+ RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
40
40
  ENTRYPOINT ["secator"]
@@ -32,6 +32,6 @@ RUN pipx install . && \
32
32
  secator install addons mongodb && \
33
33
  secator install addons redis && \
34
34
  secator install addons dev
35
- RUN secator config set security.force_source_install true
36
- RUN secator install tools --cleanup --fail-fast
35
+ RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
36
+ RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
37
37
  ENTRYPOINT ["secator"]
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.13.0](https://github.com/freelabz/secator/compare/v0.12.0...v0.13.0) (2025-04-29)
4
+
5
+
6
+ ### Features
7
+
8
+ * **core:** restore default task opts, improve workflows ([#560](https://github.com/freelabz/secator/issues/560)) ([4849d44](https://github.com/freelabz/secator/commit/4849d44448f52529380a6d9163a1b4db54114958))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * use distro.like() instead of distro.id() ([#604](https://github.com/freelabz/secator/issues/604)) ([15157d4](https://github.com/freelabz/secator/commit/15157d433a0c60292ed91bb26f513a10f15924c2))
14
+
15
+ ## [0.12.0](https://github.com/freelabz/secator/compare/v0.11.1...v0.12.0) (2025-04-24)
16
+
17
+
18
+ ### Features
19
+
20
+ * add --show option to display yaml ([#601](https://github.com/freelabz/secator/issues/601)) ([8edffe9](https://github.com/freelabz/secator/commit/8edffe9f879bb7a99a7e5fead1a18dbf6da5d140))
21
+ * **arjun:** add --disable-redirects opts ([#598](https://github.com/freelabz/secator/issues/598)) ([17618c7](https://github.com/freelabz/secator/commit/17618c7ca647536207a96ce2c235ec5227db2cef))
22
+ * **workflows:** improve url params fuzz workflow ([#597](https://github.com/freelabz/secator/issues/597)) ([38fa1bc](https://github.com/freelabz/secator/commit/38fa1bcd76c9c6dbe0bc85c9c8c707ae642b9830))
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * better options overrides for CLI ([#596](https://github.com/freelabz/secator/issues/596)) ([74e256b](https://github.com/freelabz/secator/commit/74e256b434d36f1e16390f8d06571e726517f5ce))
28
+ * worker quiet option ([#602](https://github.com/freelabz/secator/issues/602)) ([9b2c084](https://github.com/freelabz/secator/commit/9b2c08458e3412a89ec39547a728a26885fe1162))
29
+
3
30
  ## [0.11.1](https://github.com/freelabz/secator/compare/v0.11.0...v0.11.1) (2025-04-23)
4
31
 
5
32
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: secator
3
- Version: 0.11.1
3
+ Version: 0.13.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
@@ -4,7 +4,7 @@ build-backend = 'hatchling.build'
4
4
 
5
5
  [project]
6
6
  name = 'secator'
7
- version = "0.11.1"
7
+ version = "0.13.0"
8
8
  authors = [{ name = 'FreeLabz', email = 'sales@freelabz.com' }]
9
9
  readme = 'README.md'
10
10
  description = "The pentester's swiss knife."
@@ -37,7 +37,7 @@ ALL_TASKS = discover_tasks()
37
37
  ALL_WORKFLOWS = [t for t in TEMPLATES if t.type == 'workflow']
38
38
  ALL_SCANS = [t for t in TEMPLATES if t.type == 'scan']
39
39
  FINDING_TYPES_LOWER = [c.__name__.lower() for c in FINDING_TYPES]
40
- CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
40
+ CONTEXT_SETTINGS = dict(help_option_names=['-h', '-help', '--help'])
41
41
 
42
42
 
43
43
  #-----#
@@ -46,15 +46,16 @@ CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
46
46
 
47
47
 
48
48
  @click.group(cls=OrderedGroup, invoke_without_command=True, context_settings=CONTEXT_SETTINGS)
49
- @click.option('--version', '-version', is_flag=True, default=False)
49
+ @click.option('--version', '-version', '-v', is_flag=True, default=False)
50
+ @click.option('--quiet', '-quiet', '-q', is_flag=True, default=False)
50
51
  @click.pass_context
51
- def cli(ctx, version):
52
+ def cli(ctx, version, quiet):
52
53
  """Secator CLI."""
53
54
  ctx.obj = {
54
55
  'piped_input': S_ISFIFO(os.fstat(0).st_mode),
55
56
  'piped_output': not sys.stdout.isatty()
56
57
  }
57
- if not ctx.obj['piped_output']:
58
+ if not ctx.obj['piped_output'] and not quiet:
58
59
  console.print(ASCII, highlight=False)
59
60
  if ctx.invoked_subcommand is None:
60
61
  if version:
@@ -67,11 +68,16 @@ def cli(ctx, version):
67
68
  # TASK #
68
69
  #------#
69
70
 
70
- @cli.group(aliases=['x', 't'])
71
+ @cli.group(aliases=['x', 't'], invoke_without_command=True)
72
+ @click.option('--list', '-list', is_flag=True, default=False)
71
73
  @click.pass_context
72
- def task(ctx):
74
+ def task(ctx, list=False):
73
75
  """Run a task."""
74
- pass
76
+ if list:
77
+ print("\n".join(sorted([t.__name__ for t in ALL_TASKS])))
78
+ return
79
+ if ctx.invoked_subcommand is None:
80
+ ctx.get_help()
75
81
 
76
82
 
77
83
  for cls in ALL_TASKS:
@@ -83,11 +89,16 @@ for cls in ALL_TASKS:
83
89
  #----------#
84
90
 
85
91
 
86
- @cli.group(cls=OrderedGroup, aliases=['w'])
92
+ @cli.group(cls=OrderedGroup, aliases=['w'], invoke_without_command=True)
93
+ @click.option('--list', '-list', is_flag=True, default=False)
87
94
  @click.pass_context
88
- def workflow(ctx):
95
+ def workflow(ctx, list=False):
89
96
  """Run a workflow."""
90
- pass
97
+ if list:
98
+ print("\n".join(sorted([t.name for t in ALL_WORKFLOWS])))
99
+ return
100
+ if ctx.invoked_subcommand is None:
101
+ ctx.get_help()
91
102
 
92
103
 
93
104
  for config in sorted(ALL_WORKFLOWS, key=lambda x: x['name']):
@@ -98,11 +109,16 @@ for config in sorted(ALL_WORKFLOWS, key=lambda x: x['name']):
98
109
  # SCAN #
99
110
  #------#
100
111
 
101
- @cli.group(cls=OrderedGroup, aliases=['s'])
112
+ @cli.group(cls=OrderedGroup, aliases=['s'], invoke_without_command=True)
113
+ @click.option('--list', '-list', is_flag=True, default=False)
102
114
  @click.pass_context
103
- def scan(ctx):
115
+ def scan(ctx, list=False):
104
116
  """Run a scan."""
105
- pass
117
+ if list:
118
+ print("\n".join(sorted([t.name for t in ALL_SCANS])))
119
+ return
120
+ if ctx.invoked_subcommand is None:
121
+ ctx.get_help()
106
122
 
107
123
 
108
124
  for config in sorted(ALL_SCANS, key=lambda x: x['name']):
@@ -119,7 +135,7 @@ for config in sorted(ALL_SCANS, key=lambda x: x['name']):
119
135
  @click.option('-r', '--reload', is_flag=True, help='Autoreload Celery on code changes.')
120
136
  @click.option('-Q', '--queue', type=str, default='', help='Listen to a specific queue.')
121
137
  @click.option('-P', '--pool', type=str, default='eventlet', help='Pool implementation.')
122
- @click.option('--quiet', is_flag=True, help='Quiet mode.')
138
+ @click.option('--quiet', is_flag=True, default=False, help='Quiet mode.')
123
139
  @click.option('--loglevel', type=str, default='INFO', help='Log level.')
124
140
  @click.option('--check', is_flag=True, help='Check if Celery worker is alive.')
125
141
  @click.option('--dev', is_flag=True, help='Start a worker in dev mode (celery multi).')
@@ -860,13 +876,21 @@ def health(json, debug, strict):
860
876
  import json as _json
861
877
  print(_json.dumps(status))
862
878
 
879
+ # Print errors and warnings
880
+ error = False
881
+ for tool, info in status['tools'].items():
882
+ if not info['installed']:
883
+ console.print(Warning(message=f'{tool} is not installed.'))
884
+ error = True
885
+ elif info['outdated']:
886
+ message = (
887
+ f'{tool} is outdated (current:{info["version"]}, latest:{info["latest_version"]}).'
888
+ f' Run `secator install tools {tool}` to update it.'
889
+ )
890
+ console.print(Warning(message=message))
891
+
863
892
  # Strict mode
864
893
  if strict:
865
- error = False
866
- for tool, info in status['tools'].items():
867
- if not info['installed']:
868
- console.print(Error(message=f'{tool} is not installed.'))
869
- error = True
870
894
  if error:
871
895
  sys.exit(1)
872
896
  console.print(Info(message='Strict healthcheck passed !'))
@@ -1061,16 +1085,27 @@ def install_tools(cmds, cleanup, fail_fast):
1061
1085
  if CONFIG.offline_mode:
1062
1086
  console.print(Error(message='Cannot run this command in offline mode.'))
1063
1087
  return
1088
+ tools = []
1064
1089
  if cmds is not None:
1065
1090
  cmds = cmds.split(',')
1066
- tools = [cls for cls in ALL_TASKS if cls.__name__ in cmds]
1091
+ for cmd in cmds:
1092
+ if '==' in cmd:
1093
+ cmd, version = tuple(cmd.split('=='))
1094
+ else:
1095
+ cmd, version = cmd, None
1096
+ cls = next((cls for cls in ALL_TASKS if cls.__name__ == cmd), None)
1097
+ if cls:
1098
+ if version:
1099
+ cls.install_version = version
1100
+ tools.append(cls)
1101
+ else:
1102
+ console.print(Warning(message=f'Tool {cmd} is not supported or inexistent.'))
1067
1103
  else:
1068
1104
  tools = ALL_TASKS
1069
1105
  tools.sort(key=lambda x: x.__name__)
1070
1106
  return_code = 0
1071
1107
  if not tools:
1072
- cmd_str = ' '.join(cmds)
1073
- console.print(Error(message=f'No tools found for {cmd_str}.'))
1108
+ console.print(Error(message='No tools found for installing.'))
1074
1109
  return
1075
1110
  for ix, cls in enumerate(tools):
1076
1111
  # with console.status(f'[bold yellow][{ix + 1}/{len(tools)}] Installing {cls.__name__} ...'):
@@ -1140,7 +1175,7 @@ def update(all):
1140
1175
  cmd = cls.cmd.split(' ')[0]
1141
1176
  version_flag = cls.get_version_flag()
1142
1177
  info = get_version_info(cmd, version_flag, cls.install_github_handle)
1143
- if not info['installed'] or info['status'] == 'outdated' or not info['latest_version']:
1178
+ if not info['installed'] or info['outdated'] or not info['latest_version']:
1144
1179
  # with console.status(f'[bold yellow]Installing {cls.__name__} ...'):
1145
1180
  status = ToolInstaller.install(cls)
1146
1181
  if not status.is_ok():
@@ -1375,73 +1410,147 @@ def performance(tasks, workflows, scans, test):
1375
1410
  @test.command()
1376
1411
  @click.argument('name', type=str)
1377
1412
  @click.option('--verbose', '-v', is_flag=True, default=False, help='Print verbose output')
1378
- def task(name, verbose):
1379
- """Test task."""
1413
+ @click.option('--check', '-c', is_flag=True, default=False, help='Check task semantics only (no unit + integration tests)') # noqa: E501
1414
+ def task(name, verbose, check):
1415
+ """Test a single task for semantics errors, and run unit + integration tests."""
1416
+ console.print(f'[bold gold3]:wrench: Testing task {name} ...[/]')
1380
1417
  task = [task for task in ALL_TASKS if task.__name__ == name]
1381
1418
  warnings = []
1419
+ errors = []
1382
1420
  exit_code = 0
1383
1421
 
1384
1422
  # Check if task is correctly registered
1385
- check_error(task, 'Check task is registered', 'Task is not registered. Make sure there is no syntax errors in the task class definition.', warnings) # noqa: E501
1386
1423
  task = task[0]
1387
1424
  task_name = task.__name__
1388
1425
 
1389
1426
  # Run install
1390
- console.print(f'\n[bold gold3]:wrench: Running install tests for task {name} ...[/]') if verbose else None
1391
1427
  cmd = f'secator install tools {task_name}'
1392
1428
  ret_code = Command.execute(cmd, name='install', quiet=not verbose, cwd=ROOT_FOLDER)
1393
1429
  version_info = task.get_version_info()
1394
- check_error(version_info['installed'], 'Check task is installed', 'Failed to install command. Fix your installation command.', warnings) # noqa: E501
1395
- check_error(any(cmd for cmd in [task.install_cmd, task.install_github_handle]), 'Check task installation command is defined', 'Task has no installation command. Please define a `install_cmd` or `install_github_handle` class attribute.', warnings) # noqa: E501
1396
- check_error(version_info['version'], 'Check task version can be fetched', 'Failed to detect version info. Fix your `version_flag` class attribute.', warnings) # noqa: E501
1430
+ if verbose:
1431
+ console.print(f'Version info:\n{version_info}')
1432
+ status = version_info['status']
1433
+ check_test(
1434
+ version_info['installed'],
1435
+ 'Check task is installed',
1436
+ 'Failed to install command. Fix your installation command.',
1437
+ errors
1438
+ )
1439
+ check_test(
1440
+ any(cmd for cmd in [task.install_cmd, task.install_github_handle]),
1441
+ 'Check task installation command is defined',
1442
+ 'Task has no installation command. Please define one or more of the following class attributes: `install_pre`, `install_cmd`, `install_post`, `install_github_handle`.', # noqa: E501
1443
+ errors
1444
+ )
1445
+ check_test(
1446
+ version_info['version'],
1447
+ 'Check task version can be fetched',
1448
+ 'Failed to detect current version. Consider updating your `version_flag` class attribute.',
1449
+ warnings,
1450
+ warn=True
1451
+ )
1452
+ check_test(
1453
+ status != 'latest unknown',
1454
+ 'Check latest version',
1455
+ 'Failed to detect latest version.',
1456
+ warnings,
1457
+ warn=True
1458
+ )
1459
+ check_test(
1460
+ not version_info['outdated'],
1461
+ 'Check task version is up to date',
1462
+ f'Task is not up to date (current version: {version_info["version"]}, latest: {version_info["latest_version"]}). Consider updating your `install_version` class attribute.', # noqa: E501
1463
+ warnings,
1464
+ warn=True
1465
+ )
1397
1466
 
1398
1467
  # Run task-specific tests
1399
- console.print(f'\n[bold gold3]:wrench: Running task-specific tests for {name} ...[/]') if verbose else None
1400
- check_error(task.__doc__, 'Check task description is set (cls.__doc__)', 'Task has no description (class docstring).', warnings) # noqa: E501
1401
- check_error(task.cmd, 'Check task command is set (cls.cmd)', 'Task has no cmd attribute.', warnings)
1402
- check_error(task.input_type, 'Check task input type is set (cls.input_type)', 'Task has no input_type attribute.', warnings) # noqa: E501
1403
- check_error(task.output_types, 'Check task output types is set (cls.output_types)', 'Task has no output_types attribute.', warnings) # noqa: E501
1404
-
1405
- # Print all warnings
1406
- exit_code = 1 if len(warnings) > 0 else 0
1407
- if exit_code == 1:
1408
- console.print()
1409
- console.print("[bold red]Issues:[/]")
1410
- for warning in warnings:
1411
- console.print(warning)
1412
- console.print()
1413
- console.print(Info(message=f'Skipping unit and integration tests for {name} due to previous errors.'))
1414
- console.print(Error(message=f'Task {name} tests failed. Please fix the issues above before making a PR.'))
1415
- sys.exit(exit_code)
1416
-
1417
- # Run unit tests
1418
- console.print(f'\n[bold gold3]:wrench: Running unit tests for {name} ...[/]') if verbose else None
1419
- cmd = f'secator test unit --tasks {name}'
1420
- ret_code = run_test(cmd, exit=False, verbose=verbose)
1421
- check_error(ret_code == 0, 'Check unit tests pass', 'Unit tests failed.', warnings)
1422
-
1423
- # Run integration tests
1424
- console.print(f'\n[bold gold3]:wrench: Running integration tests for {name} ...[/]') if verbose else None
1425
- cmd = f'secator test integration --tasks {name}'
1426
- ret_code = run_test(cmd, exit=False, verbose=verbose)
1427
- check_error(ret_code == 0, 'Check integration tests pass', 'Integration tests failed.', warnings)
1468
+ check_test(
1469
+ task.__doc__,
1470
+ 'Check task description is set (cls.__doc__)',
1471
+ 'Task has no description (class docstring).',
1472
+ errors
1473
+ )
1474
+ check_test(
1475
+ task.cmd,
1476
+ 'Check task command is set (cls.cmd)',
1477
+ 'Task has no cmd attribute.',
1478
+ errors
1479
+ )
1480
+ check_test(
1481
+ task.input_type,
1482
+ 'Check task input type is set (cls.input_type)',
1483
+ 'Task has no input_type attribute.',
1484
+ warnings,
1485
+ warn=True
1486
+ )
1487
+ check_test(
1488
+ task.output_types,
1489
+ 'Check task output types is set (cls.output_types)',
1490
+ 'Task has no output_types attribute. Consider setting some so that secator can load your task outputs.',
1491
+ warnings,
1492
+ warn=True
1493
+ )
1494
+ check_test(
1495
+ task.install_version,
1496
+ 'Check task install_version is set (cls.install_version)',
1497
+ 'Task has no install_version attribute. Consider setting it to pin the tool version and ensure it does not break in the future.', # noqa: E501
1498
+ warnings,
1499
+ warn=True
1500
+ )
1501
+
1502
+ if not check:
1503
+
1504
+ # Run unit tests
1505
+ cmd = f'secator test unit --tasks {name}'
1506
+ ret_code = run_test(cmd, exit=False, verbose=verbose)
1507
+ check_test(
1508
+ ret_code == 0,
1509
+ 'Check unit tests pass',
1510
+ 'Unit tests failed.',
1511
+ errors
1512
+ )
1513
+
1514
+ # Run integration tests
1515
+ cmd = f'secator test integration --tasks {name}'
1516
+ ret_code = run_test(cmd, exit=False, verbose=verbose)
1517
+ check_test(
1518
+ ret_code == 0,
1519
+ 'Check integration tests pass',
1520
+ 'Integration tests failed.',
1521
+ errors
1522
+ )
1428
1523
 
1429
1524
  # Exit with exit code
1430
- exit_code = 1 if len(warnings) > 0 else 0
1525
+ exit_code = 1 if len(errors) > 0 else 0
1431
1526
  if exit_code == 0:
1432
- console.print(f':tada: Task {name} tests passed ! You are free to make a PR.', style='bold green')
1527
+ console.print(f':tada: Task {name} tests passed !', style='bold green')
1433
1528
  else:
1434
- console.print(Error(message=f'Task {name} tests failed. Please fix the issues above before making a PR.'))
1529
+ console.print('\n[bold gold3]Errors:[/]')
1530
+ for error in errors:
1531
+ console.print(error)
1532
+ console.print(Error(message=f'Task {name} tests failed. Please fix the issues above.'))
1435
1533
 
1534
+ if warnings:
1535
+ console.print('\n[bold gold3]Warnings:[/]')
1536
+ for warning in warnings:
1537
+ console.print(warning)
1538
+
1539
+ console.print("\n")
1436
1540
  sys.exit(exit_code)
1437
1541
 
1438
1542
 
1439
- def check_error(condition, message, error, warnings=[]):
1543
+ def check_test(condition, message, fail_message, results=[], warn=False):
1440
1544
  console.print(f'[bold magenta]:zap: {message} ...[/]', end='')
1441
1545
  if not condition:
1442
- warning = Warning(message=error)
1443
- warnings.append(warning)
1444
- console.print(' [bold red]FAILED[/]', style='dim')
1546
+ if not warn:
1547
+ error = Error(message=fail_message)
1548
+ console.print(' [bold red]FAILED[/]', style='dim')
1549
+ results.append(error)
1550
+ else:
1551
+ warning = Warning(message=fail_message)
1552
+ console.print(' [bold yellow]WARNING[/]', style='dim')
1553
+ results.append(warning)
1445
1554
  else:
1446
1555
  console.print(' [bold green]OK[/]', style='dim')
1447
1556
  return True
@@ -94,6 +94,7 @@ class Runners(StrictModel):
94
94
  skip_cve_low_confidence: bool = False
95
95
  remove_duplicates: bool = False
96
96
  show_chunk_progress: bool = False
97
+ show_command_output: bool = False
97
98
 
98
99
 
99
100
  class Security(StrictModel):
@@ -7,10 +7,19 @@ input_types:
7
7
  - host
8
8
  - cidr_range
9
9
  tasks:
10
+ naabu:
11
+ description: Find open ports
12
+ ports: "-" # scan all ports
10
13
  nmap:
11
14
  description: Search for vulnerabilities on open ports
12
- skip_host_discovery: True
13
- ports: "-" # scan all ports
15
+ version_detection: True
16
+ script: vulners
17
+ targets_:
18
+ - port.host
19
+ - target.name
20
+ ports_:
21
+ - port.port
22
+ ports: "-" # default if no port found by naabu
14
23
  _group/1:
15
24
  httpx:
16
25
  description: Probe HTTP services on open ports
@@ -0,0 +1,39 @@
1
+ type: workflow
2
+ name: port_scan
3
+ alias: pscan
4
+ description: Port scan
5
+ tags: [recon, network, http, vuln]
6
+ input_types:
7
+ - host
8
+ - cidr_range
9
+ tasks:
10
+ naabu:
11
+ description: Find open ports
12
+ skip_host_discovery: True
13
+ ports: "-" # scan all ports
14
+ nmap:
15
+ description: Search for vulnerabilities on open ports
16
+ skip_host_discovery: True
17
+ version_detection: True
18
+ targets_: port.host
19
+ ports_: port.port
20
+ _group:
21
+ searchsploit:
22
+ description: Search for related exploits
23
+ targets_:
24
+ - type: port
25
+ field: '{host}~{service_name}'
26
+ condition: item._source.startswith('nmap') and len(item.service_name.split('/')) > 1
27
+ httpx:
28
+ description: Probe HTTP services on open ports
29
+ targets_:
30
+ - type: port
31
+ field: '{host}:{port}'
32
+ condition: item._source.startswith('nmap')
33
+ results:
34
+ - type: port
35
+
36
+ - type: url
37
+ condition: item.status_code != 0
38
+
39
+ - type: vulnerability
@@ -14,6 +14,11 @@ tasks:
14
14
  field: '{name}/FUZZ'
15
15
  cariddi:
16
16
  description: Crawl HTTP directories for content
17
+ info: True
18
+ secrets: True
19
+ errors: True
20
+ juicy_extensions: 1
21
+ juicy_endpoints: True
17
22
  targets_:
18
23
  - target.name
19
24
  - url.url
@@ -11,6 +11,8 @@ tasks:
11
11
  ffuf:
12
12
  description: Fuzz URL params
13
13
  wordlist: https://raw.githubusercontent.com/danielmiessler/SecLists/refs/heads/master/Discovery/Web-Content/burp-parameter-names.txt
14
+ auto_calibration: true
15
+ follow_redirect: true
14
16
  targets_:
15
17
  - type: url
16
18
  field: url