mirror of
https://github.com/j3ssie/osmedeus.git
synced 2026-09-10 19:57:47 +02:00
feat: add LLM step executor with vision and tool support, event workflow system, and inheritance
- Add LLM executor supporting OpenAI vision, tool calling, embeddings, and structured outputs - Introduce event emitter/receiver workflows with deduplication and filtering (generate_event functions) - Add workflow extends/override system enabling inheritance chains and step merge modes - Update function naming to snake_case across all testdata (fileExists→file_exists, etc.) - Add comprehensive test fixtures for linter, events, CDN, step dependencies, and extends workflows
This commit is contained in:
+2
-2
@@ -38,7 +38,7 @@ modules:
|
||||
- name: port-scan
|
||||
depends_on:
|
||||
- subdomain-enum
|
||||
condition: "fileLength('{{all_subdomains}}') > 0"
|
||||
condition: "file_length('{{all_subdomains}}') > 0"
|
||||
steps:
|
||||
- name: setup-ports
|
||||
type: bash
|
||||
@@ -68,7 +68,7 @@ modules:
|
||||
- name: screenshot
|
||||
depends_on:
|
||||
- port-scan
|
||||
condition: "fileLength('{{all_ports}}') > 0"
|
||||
condition: "file_length('{{all_ports}}') > 0"
|
||||
steps:
|
||||
- name: setup-screenshots
|
||||
type: bash
|
||||
|
||||
+14
-14
@@ -31,8 +31,8 @@ steps:
|
||||
- name: validate-dependencies
|
||||
type: function
|
||||
function: |
|
||||
fileExists("{{Binaries}}/metabigor") &&
|
||||
fileExists("{{Binaries}}/httpx")
|
||||
file_exists("{{Binaries}}/metabigor") &&
|
||||
file_exists("{{Binaries}}/httpx")
|
||||
exports:
|
||||
deps_valid: "output"
|
||||
on_error:
|
||||
@@ -63,14 +63,14 @@ steps:
|
||||
|
||||
- name: clean-portscan-results
|
||||
type: function
|
||||
pre_condition: 'fileExists("{{output_dir}}/raw-open-ports.txt")'
|
||||
pre_condition: 'file_exists("{{output_dir}}/raw-open-ports.txt")'
|
||||
function: CleanRustScan("{{output_dir}}/raw-open-ports.txt", "{{output_dir}}/open-ports.txt")
|
||||
exports:
|
||||
clean_ports_file: "{{output_dir}}/open-ports.txt"
|
||||
|
||||
- name: count-open-ports
|
||||
type: function
|
||||
function: fileLength("{{output_dir}}/open-ports.txt")
|
||||
function: file_length("{{output_dir}}/open-ports.txt")
|
||||
exports:
|
||||
open_port_count: "output"
|
||||
|
||||
@@ -102,12 +102,12 @@ steps:
|
||||
|
||||
- name: sort-http-results
|
||||
type: function
|
||||
pre_condition: 'fileExists("{{httpFile}}")'
|
||||
pre_condition: 'file_exists("{{httpFile}}")'
|
||||
function: SortU("{{httpFile}}")
|
||||
|
||||
- name: count-http-hosts
|
||||
type: function
|
||||
function: fileLength("{{httpFile}}")
|
||||
function: file_length("{{httpFile}}")
|
||||
exports:
|
||||
http_host_count: "output"
|
||||
|
||||
@@ -116,7 +116,7 @@ steps:
|
||||
# ============================================================
|
||||
- name: http-fingerprinting
|
||||
type: parallel-steps
|
||||
pre_condition: 'parseInt("{{http_host_count}}") > 0'
|
||||
pre_condition: 'parse_int("{{http_host_count}}") > 0'
|
||||
parallel_steps:
|
||||
- name: httpx-json-fingerprint
|
||||
type: bash
|
||||
@@ -139,14 +139,14 @@ steps:
|
||||
# ============================================================
|
||||
- name: clean-http-json
|
||||
type: function
|
||||
pre_condition: 'fileExists("{{output_dir}}/{{Workspace}}-http-overview.txt")'
|
||||
pre_condition: 'file_exists("{{output_dir}}/{{Workspace}}-http-overview.txt")'
|
||||
function: CleanJSONHttpx("{{output_dir}}/{{Workspace}}-http-overview.txt", "{{output_dir}}/{{Workspace}}-raw-overview.txt")
|
||||
exports:
|
||||
raw_overview: "{{output_dir}}/{{Workspace}}-raw-overview.txt"
|
||||
|
||||
- name: beautify-results
|
||||
type: bash
|
||||
pre_condition: 'fileExists("{{output_dir}}/{{Workspace}}-raw-overview.txt")'
|
||||
pre_condition: 'file_exists("{{output_dir}}/{{Workspace}}-raw-overview.txt")'
|
||||
command: "cat {{output_dir}}/{{Workspace}}-raw-overview.txt | csvtk pretty --no-header-row -I -s ' | ' -W 75 > {{output_dir}}/beautify-{{Workspace}}-http.txt"
|
||||
on_error:
|
||||
- action: log
|
||||
@@ -156,7 +156,7 @@ steps:
|
||||
|
||||
- name: fallback-beautify
|
||||
type: bash
|
||||
pre_condition: '!fileExists("{{output_dir}}/beautify-{{Workspace}}-http.txt")'
|
||||
pre_condition: '!file_exists("{{output_dir}}/beautify-{{Workspace}}-http.txt")'
|
||||
command: "cp {{output_dir}}/{{Workspace}}-raw-overview.txt {{output_dir}}/beautify-{{Workspace}}-http.txt 2>/dev/null || touch {{output_dir}}/beautify-{{Workspace}}-http.txt"
|
||||
|
||||
# ============================================================
|
||||
@@ -164,7 +164,7 @@ steps:
|
||||
# ============================================================
|
||||
- name: detailed-host-analysis
|
||||
type: foreach
|
||||
pre_condition: 'parseInt("{{http_host_count}}") > 0 && parseInt("{{http_host_count}}") < 100'
|
||||
pre_condition: 'parse_int("{{http_host_count}}") > 0 && parse_int("{{http_host_count}}") < 100'
|
||||
input: "{{httpFile}}"
|
||||
variable: host
|
||||
threads: 5
|
||||
@@ -199,7 +199,7 @@ steps:
|
||||
|
||||
- name: generate-markdown-report
|
||||
type: function
|
||||
pre_condition: 'fileExists("{{Data}}/markdown/simple-template.md")'
|
||||
pre_condition: 'file_exists("{{Data}}/markdown/simple-template.md")'
|
||||
function: GenMarkdownReport("{{Data}}/markdown/simple-template.md", "{{Output}}/summary.html")
|
||||
on_error:
|
||||
- action: log
|
||||
@@ -222,10 +222,10 @@ steps:
|
||||
# ============================================================
|
||||
- name: final-sort
|
||||
type: function
|
||||
pre_condition: 'fileExists("{{httpFile}}")'
|
||||
pre_condition: 'file_exists("{{httpFile}}")'
|
||||
function: SortU("{{httpFile}}")
|
||||
|
||||
- name: notify-completion
|
||||
type: function
|
||||
pre_condition: 'parseInt("{{open_port_count}}") > 0'
|
||||
pre_condition: 'parse_int("{{open_port_count}}") > 0'
|
||||
function: printf("CIDR scan complete: {{open_port_count}} open ports, {{http_host_count}} HTTP hosts")
|
||||
|
||||
+3
-3
@@ -33,7 +33,7 @@ steps:
|
||||
script: |
|
||||
var target = "{{Target}}";
|
||||
var wordlist = "{{wordlist_small}}";
|
||||
var threadCount = parseInt("{{threads}}");
|
||||
var threadCount = parse_int("{{threads}}");
|
||||
|
||||
// Use larger wordlist for known targets
|
||||
if (target.includes(".com") || target.includes(".org")) {
|
||||
@@ -90,7 +90,7 @@ steps:
|
||||
- name: log-statistics
|
||||
type: function
|
||||
script: |
|
||||
var count = fileLength("{{all_endpoints}}");
|
||||
var count = file_length("{{all_endpoints}}");
|
||||
log_info("Total unique endpoints discovered: " + count);
|
||||
|
||||
if (count == 0) {
|
||||
@@ -105,7 +105,7 @@ steps:
|
||||
# Step 6: foreach - Probe each endpoint for parameters
|
||||
- name: parameter-discovery
|
||||
type: foreach
|
||||
pre_condition: "fileLength('{{all_endpoints}}') > 0"
|
||||
pre_condition: "file_length('{{all_endpoints}}') > 0"
|
||||
input: "{{all_endpoints}}"
|
||||
variable: endpoint
|
||||
threads: "{{threads}}"
|
||||
|
||||
+6
-6
@@ -52,7 +52,7 @@ steps:
|
||||
- name: determine-strategy
|
||||
type: function
|
||||
script: |
|
||||
var fileCount = fileLength("{{file_list}}");
|
||||
var fileCount = file_length("{{file_list}}");
|
||||
log_info("Files to process: " + fileCount);
|
||||
|
||||
if (fileCount == 0) {
|
||||
@@ -158,11 +158,11 @@ steps:
|
||||
log_info("Deduplicating aggregated data");
|
||||
|
||||
var txtFile = "{{aggregated_dir}}/all-txt.txt";
|
||||
if (fileExists(txtFile)) {
|
||||
var lineCount = fileLength(txtFile);
|
||||
if (file_exists(txtFile)) {
|
||||
var lineCount = file_length(txtFile);
|
||||
log_info("Text entries before dedup: " + lineCount);
|
||||
sortUnix(txtFile);
|
||||
var newCount = fileLength(txtFile);
|
||||
sort_unix(txtFile);
|
||||
var newCount = file_length(txtFile);
|
||||
log_info("Text entries after dedup: " + newCount);
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ steps:
|
||||
script: |
|
||||
var stats = {
|
||||
processing_mode: "{{processing_mode}}",
|
||||
files_processed: fileLength("{{file_list}}"),
|
||||
files_processed: file_length("{{file_list}}"),
|
||||
dedup_enabled: "{{enable_dedup}}" === "true",
|
||||
output_format: "{{output_format}}",
|
||||
completion_time: timestamp()
|
||||
|
||||
@@ -59,7 +59,7 @@ modules:
|
||||
- name: vuln-scan
|
||||
depends_on:
|
||||
- recon
|
||||
condition: "fileLength('{{all_subdomains}}') > 0"
|
||||
condition: "file_length('{{all_subdomains}}') > 0"
|
||||
steps:
|
||||
- name: init-vulns
|
||||
type: bash
|
||||
@@ -121,18 +121,18 @@ modules:
|
||||
scan_depth: "{{scan_depth}}",
|
||||
timestamp: timestamp(),
|
||||
statistics: {
|
||||
subdomains: fileLength("{{all_subdomains}}"),
|
||||
http_hosts: fileLength("{{http_hosts}}"),
|
||||
subdomains: file_length("{{all_subdomains}}"),
|
||||
http_hosts: file_length("{{http_hosts}}"),
|
||||
critical_findings: 0,
|
||||
medium_findings: 0
|
||||
}
|
||||
};
|
||||
|
||||
if (fileExists("{{critical_vulns}}")) {
|
||||
summary.statistics.critical_findings = fileLength("{{critical_vulns}}");
|
||||
if (file_exists("{{critical_vulns}}")) {
|
||||
summary.statistics.critical_findings = file_length("{{critical_vulns}}");
|
||||
}
|
||||
if (fileExists("{{medium_vulns}}")) {
|
||||
summary.statistics.medium_findings = fileLength("{{medium_vulns}}");
|
||||
if (file_exists("{{medium_vulns}}")) {
|
||||
summary.statistics.medium_findings = file_length("{{medium_vulns}}");
|
||||
}
|
||||
|
||||
log_info("Assessment Summary:");
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ steps:
|
||||
|
||||
- name: httpx-fingerprint
|
||||
type: bash
|
||||
pre_condition: "fileExists('{{httpFile}}')"
|
||||
pre_condition: "file_exists('{{httpFile}}')"
|
||||
command: >
|
||||
cat {{httpFile}} | {{Binaries}}/httpx -H '{{defaultUA}}' -timeout {{httpTimeout}}
|
||||
-t {{httpThreads}} -no-fallback -no-color -silent -json -title -favicon
|
||||
|
||||
+2
-2
@@ -70,7 +70,7 @@ steps:
|
||||
- name: analyze-results
|
||||
type: function
|
||||
script: |
|
||||
var portCount = fileLength("{{open_ports}}");
|
||||
var portCount = file_length("{{open_ports}}");
|
||||
log_info("Total open ports found: " + portCount);
|
||||
if (portCount == 0) {
|
||||
return "no_ports";
|
||||
@@ -108,7 +108,7 @@ steps:
|
||||
# Step 7: bash - Batch service detection for many ports
|
||||
- name: batch-service-detection
|
||||
type: bash
|
||||
pre_condition: "fileLength('{{open_ports}}') > 100"
|
||||
pre_condition: "file_length('{{open_ports}}') > 100"
|
||||
command: "{{Binaries}}/nmap -sV --version-intensity 5 -iL {{open_ports}} -oN {{services_dir}}/batch-scan.txt"
|
||||
timeout: 7200
|
||||
exports:
|
||||
|
||||
+9
-9
@@ -33,13 +33,13 @@ steps:
|
||||
var urls = [];
|
||||
|
||||
// Check if target is a file or single URL
|
||||
if (fileExists(target)) {
|
||||
if (file_exists(target)) {
|
||||
log_info("Target is a file, reading URLs");
|
||||
var content = readFile(target);
|
||||
var content = read_file(target);
|
||||
urls = content.trim().split("\n").filter(function(u) { return u.length > 0; });
|
||||
} else {
|
||||
// Ensure URL has protocol
|
||||
if (!target.startsWith("http")) {
|
||||
if (!target.starts_with("http")) {
|
||||
target = "https://" + target;
|
||||
}
|
||||
urls = [target];
|
||||
@@ -56,7 +56,7 @@ steps:
|
||||
# Step 3: bash with pre_condition - Quick probe to filter live URLs
|
||||
- name: probe-live-urls
|
||||
type: bash
|
||||
pre_condition: "fileExists('{{url_list}}')"
|
||||
pre_condition: "file_exists('{{url_list}}')"
|
||||
command: "{{Binaries}}/httpx -l {{url_list}} -silent -mc 200,201,301,302,307,401,403 -o {{Output}}/live-urls.txt"
|
||||
timeout: 600
|
||||
on_error: continue
|
||||
@@ -66,9 +66,9 @@ steps:
|
||||
# Step 4: function - Check live URL count before proceeding
|
||||
- name: validate-live-urls
|
||||
type: function
|
||||
pre_condition: "fileExists('{{live_urls}}')"
|
||||
pre_condition: "file_exists('{{live_urls}}')"
|
||||
script: |
|
||||
var count = fileLength("{{live_urls}}");
|
||||
var count = file_length("{{live_urls}}");
|
||||
log_info("Live URLs found: " + count);
|
||||
|
||||
if (count == 0) {
|
||||
@@ -83,7 +83,7 @@ steps:
|
||||
# Step 5: foreach - Capture screenshots of each URL
|
||||
- name: capture-screenshots
|
||||
type: foreach
|
||||
pre_condition: "fileExists('{{live_urls}}') && fileLength('{{live_urls}}') > 0"
|
||||
pre_condition: "file_exists('{{live_urls}}') && file_length('{{live_urls}}') > 0"
|
||||
input: "{{live_urls}}"
|
||||
variable: url
|
||||
threads: "{{threads}}"
|
||||
@@ -128,8 +128,8 @@ steps:
|
||||
type: function
|
||||
script: |
|
||||
var stats = {
|
||||
total_urls: parseInt("{{url_count}}"),
|
||||
live_urls: fileLength("{{live_urls}}"),
|
||||
total_urls: parse_int("{{url_count}}"),
|
||||
live_urls: file_length("{{live_urls}}"),
|
||||
screenshots: 0,
|
||||
thumbnails: 0
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@ steps:
|
||||
type: function
|
||||
script: |
|
||||
log_info("Starting subdomain enumeration for: {{Target}}");
|
||||
if (isEmpty("{{Target}}")) {
|
||||
if (is_empty("{{Target}}")) {
|
||||
log_error("Target is empty");
|
||||
return false;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ steps:
|
||||
- name: check-results
|
||||
type: function
|
||||
script: |
|
||||
var count = fileLength("{{all_subdomains}}");
|
||||
var count = file_length("{{all_subdomains}}");
|
||||
log_info("Found " + count + " unique subdomains");
|
||||
if (count == 0) {
|
||||
log_warn("No subdomains found, trying bruteforce");
|
||||
@@ -73,7 +73,7 @@ steps:
|
||||
# Step 6: bash with pre_condition - Active bruteforce if passive found few results
|
||||
- name: active-bruteforce
|
||||
type: bash
|
||||
pre_condition: "fileLength('{{all_subdomains}}') < 50"
|
||||
pre_condition: "file_length('{{all_subdomains}}') < 50"
|
||||
command: "{{Binaries}}/puredns bruteforce {{wordlist}} {{Target}} -r {{resolvers}} -w {{subdomain_dir}}/bruteforce.txt"
|
||||
timeout: 1800
|
||||
on_error: continue
|
||||
|
||||
@@ -39,7 +39,7 @@ steps:
|
||||
log_info(" Severity: {{severity}}");
|
||||
log_info(" Threads: {{threads}}");
|
||||
|
||||
if (!fileExists("{{templates_path}}")) {
|
||||
if (!file_exists("{{templates_path}}")) {
|
||||
log_warn("Templates path not found, using default");
|
||||
}
|
||||
return true;
|
||||
@@ -71,7 +71,7 @@ steps:
|
||||
# Step 5: foreach - Check each finding for exploitability
|
||||
- name: verify-findings
|
||||
type: foreach
|
||||
pre_condition: "fileExists('{{nuclei_results}}')"
|
||||
pre_condition: "file_exists('{{nuclei_results}}')"
|
||||
input: "{{nuclei_results}}"
|
||||
variable: finding
|
||||
threads: 5
|
||||
@@ -111,8 +111,8 @@ steps:
|
||||
var high = 0;
|
||||
var medium = 0;
|
||||
|
||||
if (fileExists("{{nuclei_results}}")) {
|
||||
var content = readFile("{{nuclei_results}}");
|
||||
if (file_exists("{{nuclei_results}}")) {
|
||||
var content = read_file("{{nuclei_results}}");
|
||||
critical = (content.match(/critical/gi) || []).length;
|
||||
high = (content.match(/high/gi) || []).length;
|
||||
medium = (content.match(/medium/gi) || []).length;
|
||||
|
||||
+3
-3
@@ -46,7 +46,7 @@ modules:
|
||||
- name: scanning
|
||||
depends_on:
|
||||
- discovery
|
||||
condition: "fileLength('{{all_endpoints}}') > 0"
|
||||
condition: "file_length('{{all_endpoints}}') > 0"
|
||||
steps:
|
||||
- name: init-scanning
|
||||
type: bash
|
||||
@@ -95,8 +95,8 @@ modules:
|
||||
var findings = [];
|
||||
var nucleiFile = "{{nuclei_results}}";
|
||||
|
||||
if (fileExists(nucleiFile)) {
|
||||
var content = readFile(nucleiFile);
|
||||
if (file_exists(nucleiFile)) {
|
||||
var content = read_file(nucleiFile);
|
||||
var lines = content.split("\n").filter(function(l) { return l.trim().length > 0; });
|
||||
findings = lines.map(function(l) {
|
||||
try { return JSON.parse(l); } catch(e) { return {raw: l}; }
|
||||
|
||||
+21
-21
@@ -45,8 +45,8 @@ steps:
|
||||
- name: validate-dependencies
|
||||
type: function
|
||||
function: |
|
||||
fileExists("{{Binaries}}/jaeles") &&
|
||||
fileExists("{{Binaries}}/nuclei")
|
||||
file_exists("{{Binaries}}/jaeles") &&
|
||||
file_exists("{{Binaries}}/nuclei")
|
||||
exports:
|
||||
deps_valid: "output"
|
||||
on_error:
|
||||
@@ -71,7 +71,7 @@ steps:
|
||||
# ============================================================
|
||||
- name: check-input-exists
|
||||
type: function
|
||||
function: fileExists("{{httpFile}}")
|
||||
function: file_exists("{{httpFile}}")
|
||||
exports:
|
||||
input_exists: "output"
|
||||
on_error:
|
||||
@@ -81,7 +81,7 @@ steps:
|
||||
|
||||
- name: count-input-lines
|
||||
type: function
|
||||
function: fileLength("{{httpFile}}")
|
||||
function: file_length("{{httpFile}}")
|
||||
exports:
|
||||
input_count: "output"
|
||||
|
||||
@@ -89,8 +89,8 @@ steps:
|
||||
- name: check-input-limit
|
||||
type: function
|
||||
function: |
|
||||
var count = parseInt("{{input_count}}");
|
||||
var limit = parseInt("{{limit}}");
|
||||
var count = parse_int("{{input_count}}");
|
||||
var limit = parse_int("{{limit}}");
|
||||
if (count > limit) {
|
||||
return "exceeds_limit";
|
||||
}
|
||||
@@ -128,7 +128,7 @@ steps:
|
||||
|
||||
- name: count-split-files
|
||||
type: function
|
||||
function: fileLength("{{output_dir}}/raw/split-files.txt")
|
||||
function: file_length("{{output_dir}}/raw/split-files.txt")
|
||||
exports:
|
||||
split_count: "output"
|
||||
|
||||
@@ -137,7 +137,7 @@ steps:
|
||||
# ============================================================
|
||||
- name: jaeles-active-scan
|
||||
type: foreach
|
||||
pre_condition: 'parseInt("{{split_count}}") > 0'
|
||||
pre_condition: 'parse_int("{{split_count}}") > 0'
|
||||
input: "{{output_dir}}/raw/split-files.txt"
|
||||
variable: splitfile
|
||||
threads: 1
|
||||
@@ -151,7 +151,7 @@ steps:
|
||||
|
||||
- name: jaeles-sensitive-scan
|
||||
type: foreach
|
||||
pre_condition: 'parseInt("{{split_count}}") > 0'
|
||||
pre_condition: 'parse_int("{{split_count}}") > 0'
|
||||
input: "{{output_dir}}/raw/split-files.txt"
|
||||
variable: splitfile
|
||||
threads: 1
|
||||
@@ -186,14 +186,14 @@ steps:
|
||||
# ============================================================
|
||||
- name: copy-active-summary
|
||||
type: bash
|
||||
pre_condition: 'fileExists("{{output_dir}}/active/jaeles-summary.txt")'
|
||||
pre_condition: 'file_exists("{{output_dir}}/active/jaeles-summary.txt")'
|
||||
command: "cp {{output_dir}}/active/jaeles-summary.txt {{output_dir}}/active/activescan-{{Workspace}}-{{TS}}.txt"
|
||||
exports:
|
||||
active_summary: "{{output_dir}}/active/activescan-{{Workspace}}-{{TS}}.txt"
|
||||
|
||||
- name: notify-active-results
|
||||
type: function
|
||||
pre_condition: 'fileExists("{{output_dir}}/active/activescan-{{Workspace}}-{{TS}}.txt")'
|
||||
pre_condition: 'file_exists("{{output_dir}}/active/activescan-{{Workspace}}-{{TS}}.txt")'
|
||||
parallel_functions:
|
||||
- TeleMessByFile("#report", "{{output_dir}}/active/activescan-{{Workspace}}-{{TS}}.txt")
|
||||
- Cat("{{output_dir}}/active/activescan-{{Workspace}}-{{TS}}.txt")
|
||||
@@ -205,14 +205,14 @@ steps:
|
||||
|
||||
- name: copy-sensitive-summary
|
||||
type: bash
|
||||
pre_condition: 'fileExists("{{output_dir}}/sensitive/jaeles-summary.txt")'
|
||||
pre_condition: 'file_exists("{{output_dir}}/sensitive/jaeles-summary.txt")'
|
||||
command: "cp {{output_dir}}/sensitive/jaeles-summary.txt {{output_dir}}/sensitive/sensitivescan-{{Workspace}}-{{TS}}.txt"
|
||||
exports:
|
||||
sensitive_summary: "{{output_dir}}/sensitive/sensitivescan-{{Workspace}}-{{TS}}.txt"
|
||||
|
||||
- name: notify-sensitive-results
|
||||
type: function
|
||||
pre_condition: 'fileExists("{{output_dir}}/sensitive/sensitivescan-{{Workspace}}-{{TS}}.txt")'
|
||||
pre_condition: 'file_exists("{{output_dir}}/sensitive/sensitivescan-{{Workspace}}-{{TS}}.txt")'
|
||||
parallel_functions:
|
||||
- TeleMessByFile("#sensitive", "{{output_dir}}/sensitive/sensitivescan-{{Workspace}}-{{TS}}.txt")
|
||||
- Cat("{{output_dir}}/sensitive/sensitivescan-{{Workspace}}-{{TS}}.txt")
|
||||
@@ -227,7 +227,7 @@ steps:
|
||||
# ============================================================
|
||||
- name: nuclei-scan
|
||||
type: bash
|
||||
pre_condition: '"{{enableNuclei}}" == "true" && fileExists("{{httpFile}}")'
|
||||
pre_condition: '"{{enableNuclei}}" == "true" && file_exists("{{httpFile}}")'
|
||||
command: |
|
||||
timeout -k 1m {{nucleiTimeout}} {{Binaries}}/nuclei \
|
||||
-H '{{defaultUA}}' \
|
||||
@@ -249,8 +249,8 @@ steps:
|
||||
|
||||
- name: count-nuclei-results
|
||||
type: function
|
||||
pre_condition: 'fileExists("{{output_dir}}/nuclei/{{Workspace}}-nuclei-json.txt")'
|
||||
function: fileLength("{{output_dir}}/nuclei/{{Workspace}}-nuclei-json.txt")
|
||||
pre_condition: 'file_exists("{{output_dir}}/nuclei/{{Workspace}}-nuclei-json.txt")'
|
||||
function: file_length("{{output_dir}}/nuclei/{{Workspace}}-nuclei-json.txt")
|
||||
exports:
|
||||
nuclei_count: "output"
|
||||
|
||||
@@ -259,7 +259,7 @@ steps:
|
||||
# ============================================================
|
||||
- name: generate-nuclei-report
|
||||
type: function
|
||||
pre_condition: 'parseInt("{{nuclei_count}}") > 0'
|
||||
pre_condition: 'parse_int("{{nuclei_count}}") > 0'
|
||||
function: GenNucleiReport("{{output_dir}}/nuclei/{{Workspace}}-nuclei-json.txt", "{{output_dir}}/nuclei/{{Workspace}}-nuclei.html")
|
||||
on_error:
|
||||
- action: log
|
||||
@@ -268,7 +268,7 @@ steps:
|
||||
|
||||
- name: parse-nuclei-json
|
||||
type: bash
|
||||
pre_condition: 'parseInt("{{nuclei_count}}") > 0'
|
||||
pre_condition: 'parse_int("{{nuclei_count}}") > 0'
|
||||
command: |
|
||||
cat {{output_dir}}/nuclei/{{Workspace}}-nuclei-json.txt | \
|
||||
jq -r '[.info.severity,.\"template-id\",.\"matched-at\",.\"matched-name\"] | join(\" - \")' \
|
||||
@@ -278,12 +278,12 @@ steps:
|
||||
|
||||
- name: sort-nuclei-results
|
||||
type: function
|
||||
pre_condition: 'fileExists("{{output_dir}}/nuclei/{{Workspace}}-nuclei-scan.txt")'
|
||||
pre_condition: 'file_exists("{{output_dir}}/nuclei/{{Workspace}}-nuclei-scan.txt")'
|
||||
function: SortU("{{output_dir}}/nuclei/{{Workspace}}-nuclei-scan.txt")
|
||||
|
||||
- name: notify-nuclei-results
|
||||
type: function
|
||||
pre_condition: 'parseInt("{{nuclei_count}}") > 0'
|
||||
pre_condition: 'parse_int("{{nuclei_count}}") > 0'
|
||||
parallel_functions:
|
||||
- TeleMessByFile("#sensitive", "{{output_dir}}/nuclei/{{Workspace}}-nuclei-scan.txt")
|
||||
- Cat("{{output_dir}}/nuclei/{{Workspace}}-nuclei-scan.txt")
|
||||
@@ -297,7 +297,7 @@ steps:
|
||||
# ============================================================
|
||||
- name: generate-final-report
|
||||
type: function
|
||||
pre_condition: 'fileExists("{{Data}}/markdown/general-template.md")'
|
||||
pre_condition: 'file_exists("{{Data}}/markdown/general-template.md")'
|
||||
function: GenMarkdownReport("{{Data}}/markdown/general-template.md", "{{Output}}/summary.html")
|
||||
on_error:
|
||||
- action: log
|
||||
|
||||
+11
-11
@@ -37,9 +37,9 @@ steps:
|
||||
- name: validate-dependencies
|
||||
type: function
|
||||
function: |
|
||||
fileExists("{{Binaries}}/subfinder") &&
|
||||
fileExists("{{Binaries}}/assetfinder") &&
|
||||
fileExists("{{Binaries}}/httpx")
|
||||
file_exists("{{Binaries}}/subfinder") &&
|
||||
file_exists("{{Binaries}}/assetfinder") &&
|
||||
file_exists("{{Binaries}}/httpx")
|
||||
exports:
|
||||
deps_valid: "output"
|
||||
on_error:
|
||||
@@ -90,7 +90,7 @@ steps:
|
||||
- name: count-subdomains
|
||||
type: function
|
||||
function: |
|
||||
var count = fileLength("{{subdomains_file}}");
|
||||
var count = file_length("{{subdomains_file}}");
|
||||
return count > 0 ? "true" : "false";
|
||||
exports:
|
||||
subdomain_count: "{{Result}}"
|
||||
@@ -125,14 +125,14 @@ steps:
|
||||
|
||||
- name: fallback-probing
|
||||
type: bash
|
||||
pre_condition: "!fileExists('{{Output}}/web-recon/probing/live-{{Workspace}}.txt')"
|
||||
pre_condition: "!file_exists('{{Output}}/web-recon/probing/live-{{Workspace}}.txt')"
|
||||
command: "cat {{subdomains_file}} | xargs -I {} curl -s -o /dev/null -w '%{http_code} {}\\n' http://{} 2>/dev/null | grep '^200' | awk '{print $2}' > {{Output}}/web-recon/probing/live-{{Workspace}}.txt"
|
||||
exports:
|
||||
live_hosts_file: "{{Output}}/web-recon/probing/live-{{Workspace}}.txt"
|
||||
|
||||
- name: count-live-hosts
|
||||
type: function
|
||||
function: fileLength("{{live_hosts_file}}")
|
||||
function: file_length("{{live_hosts_file}}")
|
||||
exports:
|
||||
live_host_count: "output"
|
||||
|
||||
@@ -145,7 +145,7 @@ steps:
|
||||
# Screenshot capture using Docker
|
||||
- name: capture-screenshots
|
||||
type: remote-bash
|
||||
pre_condition: '"{{enableScreenshots}}" == "true" && parseInt("{{live_host_count}}") > 0'
|
||||
pre_condition: '"{{enableScreenshots}}" == "true" && parse_int("{{live_host_count}}") > 0'
|
||||
step_runner: docker
|
||||
step_runner_config:
|
||||
image: projectdiscovery/katana:latest
|
||||
@@ -166,7 +166,7 @@ steps:
|
||||
# Nuclei vulnerability scanning using Docker
|
||||
- name: nuclei-scan
|
||||
type: remote-bash
|
||||
pre_condition: '"{{enableNuclei}}" == "true" && parseInt("{{live_host_count}}") > 0'
|
||||
pre_condition: '"{{enableNuclei}}" == "true" && parse_int("{{live_host_count}}") > 0'
|
||||
step_runner: docker
|
||||
step_runner_config:
|
||||
image: projectdiscovery/nuclei:latest
|
||||
@@ -195,7 +195,7 @@ steps:
|
||||
# ============================================================
|
||||
- name: detailed-host-analysis
|
||||
type: foreach
|
||||
pre_condition: 'parseInt("{{live_host_count}}") > 0 && parseInt("{{live_host_count}}") < 50'
|
||||
pre_condition: 'parse_int("{{live_host_count}}") > 0 && parse_int("{{live_host_count}}") < 50'
|
||||
input: "{{live_hosts_file}}"
|
||||
variable: host
|
||||
threads: 5
|
||||
@@ -213,7 +213,7 @@ steps:
|
||||
# ============================================================
|
||||
- name: process-nuclei-results
|
||||
type: function
|
||||
pre_condition: 'fileExists("{{Output}}/web-recon/nuclei/results-{{Workspace}}.json")'
|
||||
pre_condition: 'file_exists("{{Output}}/web-recon/nuclei/results-{{Workspace}}.json")'
|
||||
parallel_functions:
|
||||
- db_vuln_critical("{{Output}}/web-recon/nuclei/results-{{Workspace}}.json")
|
||||
- db_vuln_high("{{Output}}/web-recon/nuclei/results-{{Workspace}}.json")
|
||||
@@ -259,5 +259,5 @@ steps:
|
||||
|
||||
- name: notify-completion
|
||||
type: function
|
||||
pre_condition: 'parseInt("{{subdomain_count}}") > 0'
|
||||
pre_condition: 'parse_int("{{subdomain_count}}") > 0'
|
||||
function: printf("Scan complete: {{subdomain_count}} subdomains, {{live_host_count}} live hosts")
|
||||
|
||||
Reference in New Issue
Block a user