feat: add SSH test infrastructure, improve executor temp handling, enhance CLI workflow install

Amp-Thread-ID: https://ampcode.com/threads/T-019c195d-0f3b-724a-946a-a3a93dd7d09b
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
j3ssie
2026-02-01 20:21:05 +07:00
co-authored by Amp
parent 7de3e7b2b2
commit b80c8b6ecd
13 changed files with 433 additions and 38 deletions
+38
View File
@@ -0,0 +1,38 @@
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \
openssh-server \
sudo \
curl \
wget \
vim \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir /var/run/sshd
# Create test user with sudo access
RUN useradd -m -s /bin/bash testuser \
&& echo "testuser:testpass" | chpasswd \
&& usermod -aG sudo testuser \
&& echo "testuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Setup SSH directory for testuser
RUN mkdir -p /home/testuser/.ssh \
&& chmod 700 /home/testuser/.ssh
# Copy authorized keys
COPY id_ed25519.pub /home/testuser/.ssh/authorized_keys
# Set proper permissions
RUN chmod 600 /home/testuser/.ssh/authorized_keys \
&& chown -R testuser:testuser /home/testuser/.ssh
# Configure SSH
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config \
&& sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config \
&& sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
+33
View File
@@ -0,0 +1,33 @@
# SSH Test Container
Ubuntu 22.04 container with SSH server for testing osmedeus SSH runner.
## Quick Start
```bash
# Build and start
docker-compose up -d --build
# Test SSH connection
ssh -i id_ed25519 -p 2222 testuser@localhost
# Stop
docker-compose down
```
## Credentials
- **User**: `testuser`
- **Password**: `testpass`
- **SSH Key**: `id_ed25519` (in this directory)
- **Port**: `2222`
## SSH Command Examples
```bash
# Using key authentication
ssh -i id_ed25519 -p 2222 -o StrictHostKeyChecking=no testuser@localhost
# Run command
ssh -i id_ed25519 -p 2222 -o StrictHostKeyChecking=no testuser@localhost "whoami"
```
+14
View File
@@ -0,0 +1,14 @@
services:
ssh-test:
build:
context: .
dockerfile: Dockerfile
container_name: osmedeus-ssh-test
ports:
- "2222:22"
restart: unless-stopped
healthcheck:
test: ["CMD", "pgrep", "sshd"]
interval: 10s
timeout: 5s
retries: 3
+7
View File
@@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACBFkHTIis1TLr0yQE9H+I+Oj5rkuRLmlbTLGTyYFztFogAAAKAlkswGJZLM
BgAAAAtzc2gtZWQyNTUxOQAAACBFkHTIis1TLr0yQE9H+I+Oj5rkuRLmlbTLGTyYFztFog
AAAECNG9yAIRlP1a223qsQFSig797wA4lcBJzcnjNlQCaWhkWQdMiKzVMuvTJAT0f4j46P
muS5EuaVtMsZPJgXO0WiAAAAF29zbWVkZXVzLXRlc3RAbG9jYWxob3N0AQIDBAUG
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEWQdMiKzVMuvTJAT0f4j46PmuS5EuaVtMsZPJgXO0Wi osmedeus-test@localhost
+166 -3
View File
@@ -94,6 +94,14 @@ func BuildBuiltinVariables(cfg *config.Config, params map[string]string) map[str
runUUID := uuid.New().String()
execCtx := core.NewExecutionContext("func-eval", core.KindModule, runUUID, params["target"])
exec.injectBuiltinVariables(cfg, params, execCtx)
// Add temp directory for eval (cleanup is handled by the caller)
tempDir, err := os.MkdirTemp("", "osm-tmp-")
if err == nil {
execCtx.SetVariable("TempDir", tempDir)
execCtx.SetVariable("TempFile", filepath.Join(tempDir, "osm-tmp-file"))
}
return execCtx.GetVariables()
}
@@ -170,13 +178,22 @@ func (e *Executor) writeVerboseOutputToLog(output string) {
if e.consoleCapture == nil || output == "" {
return
}
// Trim whitespace from output
output = strings.TrimSpace(output)
if output == "" {
return // Don't print [output] if nothing to show
}
// Format similar to printer.VerboseOutput but write directly to file
var sb strings.Builder
sb.WriteString(" ")
sb.WriteString(terminal.Gray("[output]"))
sb.WriteString("\n")
lines := strings.Split(strings.TrimSuffix(output, "\n"), "\n")
lines := strings.Split(output, "\n")
for _, line := range lines {
// Skip blank lines
if strings.TrimSpace(line) == "" {
continue
}
sb.WriteString(" ")
sb.WriteString(line)
sb.WriteString("\n")
@@ -372,6 +389,30 @@ func (e *Executor) injectBuiltinVariables(cfg *config.Config, params map[string]
}
}
// setupTempDirectory creates a temporary directory and file for workflow execution
// Returns a cleanup function that removes the directory when called
func (e *Executor) setupTempDirectory(execCtx *core.ExecutionContext) (cleanup func()) {
tempDir, err := os.MkdirTemp("", "osm-tmp-")
if err != nil {
e.logger.Warn("Failed to create temp directory", zap.Error(err))
return func() {} // no-op cleanup
}
execCtx.SetVariable("TempDir", tempDir)
// Create temp file path within temp dir
tempFile := filepath.Join(tempDir, "osm-tmp-file")
execCtx.SetVariable("TempFile", tempFile)
return func() {
if err := os.RemoveAll(tempDir); err != nil {
e.logger.Warn("Failed to cleanup temp directory",
zap.String("path", tempDir),
zap.Error(err))
}
}
}
func (e *Executor) debugLogTargetVariables(execCtx *core.ExecutionContext) {
if execCtx == nil || execCtx.Logger == nil {
return
@@ -578,6 +619,122 @@ func printDryRunHeader(workflowName, workflowKind, target, tactic string, stepCo
// getStepCommand extracts the command/script from a step for display
func getStepCommand(step *core.Step) string {
// Handle foreach steps specially
if step.Type == core.StepTypeForeach && step.Input != "" {
parts := []string{fmt.Sprintf("foreach [[%s]] in %s", step.Variable, step.Input)}
if step.VariablePreProcess != "" {
parts = append(parts, fmt.Sprintf("pre_process: %s", step.VariablePreProcess))
}
// Add inner step name, type, and command
if step.Step != nil && step.Step.Name != "" {
innerCmd := getInnerStepCommand(step.Step)
if innerCmd != "" {
parts = append(parts, fmt.Sprintf("step: %s (%s) cmd: %s", step.Step.Name, step.Step.Type, innerCmd))
} else {
parts = append(parts, fmt.Sprintf("step: %s (%s)", step.Step.Name, step.Step.Type))
}
}
threads, _ := step.Threads.Int()
if threads <= 0 {
threads = 1
}
parts = append(parts, fmt.Sprintf("threads: %d", threads))
return strings.Join(parts, " | ")
}
if step.Command != "" {
return step.Command
}
if len(step.Commands) > 0 {
return step.Commands[0]
}
if step.Function != "" {
return step.Function
}
if len(step.Functions) > 0 {
return step.Functions[0]
}
return ""
}
// getStepCommandColored returns a colored command string for foreach steps (for console display)
func getStepCommandColored(step *core.Step) string {
// Handle foreach steps specially with colors
if step.Type == core.StepTypeForeach && step.Input != "" {
var lines []string
// First line: foreach [[variable]] in source | threads: N
var firstLineParts []string
firstLineParts = append(firstLineParts, fmt.Sprintf("foreach %s in %s",
terminal.Magenta("[["+step.Variable+"]]"),
terminal.Cyan(step.Input)))
if step.VariablePreProcess != "" {
firstLineParts = append(firstLineParts, fmt.Sprintf("pre_process: %s", terminal.Gray(step.VariablePreProcess)))
}
threads, _ := step.Threads.Int()
if threads <= 0 {
threads = 1
}
firstLineParts = append(firstLineParts, fmt.Sprintf("threads: %s", terminal.Yellow(fmt.Sprintf("%d", threads))))
lines = append(lines, strings.Join(firstLineParts, terminal.Gray(" | ")))
// Second line: step: name (type)
if step.Step != nil && step.Step.Name != "" {
lines = append(lines, fmt.Sprintf(" %s %s %s",
terminal.Gray("step:"),
terminal.HiBlue(step.Step.Name),
terminal.Gray("("+string(step.Step.Type)+")")))
// Add command/commands/function/functions on separate lines
innerLines := getInnerStepCommandLines(step.Step)
lines = append(lines, innerLines...)
}
return strings.Join(lines, "\n")
}
// For non-foreach steps, return uncolored (will be colored by printer)
return getStepCommand(step)
}
// getInnerStepCommandLines returns colored lines for inner step commands/functions
func getInnerStepCommandLines(step *core.Step) []string {
var lines []string
if step.Command != "" {
lines = append(lines, fmt.Sprintf(" %s %s",
terminal.Gray("command:"),
terminal.HiGreen(step.Command)))
}
if len(step.Commands) > 0 {
lines = append(lines, fmt.Sprintf(" %s", terminal.Gray("commands:")))
for _, cmd := range step.Commands {
lines = append(lines, fmt.Sprintf(" %s %s",
terminal.Gray("-"),
terminal.HiGreen(cmd)))
}
}
if step.Function != "" {
lines = append(lines, fmt.Sprintf(" %s %s",
terminal.Gray("function:"),
terminal.HiCyan(step.Function)))
}
if len(step.Functions) > 0 {
lines = append(lines, fmt.Sprintf(" %s", terminal.Gray("functions:")))
for _, fn := range step.Functions {
lines = append(lines, fmt.Sprintf(" %s %s",
terminal.Gray("-"),
terminal.HiCyan(fn)))
}
}
return lines
}
// getInnerStepCommand extracts the command/function from an inner step (for logs)
func getInnerStepCommand(step *core.Step) string {
if step.Command != "" {
return step.Command
}
@@ -823,6 +980,8 @@ func (e *Executor) ExecuteModule(ctx context.Context, module *core.Workflow, par
zap.String("tactic", params["tactic"]),
)
e.injectBuiltinVariables(cfg, params, execCtx)
tempCleanup := e.setupTempDirectory(execCtx)
defer tempCleanup()
e.debugLogTargetVariables(execCtx)
if !e.dryRun && database.GetDB() != nil {
@@ -1438,6 +1597,8 @@ func (e *Executor) ExecuteFlow(ctx context.Context, flow *core.Workflow, params
// Inject builtin variables
e.logger.Debug("Injecting builtin variables for flow")
e.injectBuiltinVariables(cfg, params, execCtx)
tempCleanup := e.setupTempDirectory(execCtx)
defer tempCleanup()
e.debugLogTargetVariables(execCtx)
if !e.dryRun && database.GetDB() != nil {
@@ -2025,15 +2186,17 @@ func (e *Executor) executeStep(ctx context.Context, step *core.Step, execCtx *co
stepSymbol := terminal.StepTypeSymbol(string(step.Type), string(step.StepRunner))
cmdPrefix := terminal.StepCommandPrefix(string(step.Type))
stepCommand := getStepCommand(step)
stepCommandColored := getStepCommandColored(step)
if stepCommand != "" {
stepCommand, _ = e.templateEngine.Render(stepCommand, execCtx.GetVariables())
stepCommandColored, _ = e.templateEngine.Render(stepCommandColored, execCtx.GetVariables())
}
// Show step start (skip when progress bar is active)
if e.progressBar == nil {
e.printer.StepStartWithCommand(step.Name, stepSymbol, stepCommand, cmdPrefix)
e.printer.StepStartWithCommand(step.Name, stepSymbol, stepCommandColored, cmdPrefix)
} else {
// Update progress bar with current step command
// Update progress bar with current step command (uncolored for progress bar)
e.progressBar.SetCommand(stepCommand)
}
+16 -2
View File
@@ -130,7 +130,12 @@ func (p *Printer) StepStartWithCommand(stepName, typeSymbol, command, cmdPrefix
}
_, _ = fmt.Fprintf(os.Stdout, "%s %s %s %s\n", StepStartSymbol(), typeSymbol, Gray("(starting)"), HiBlue(stepName))
if command != "" {
_, _ = fmt.Fprintf(os.Stdout, " %s\n", HiGreen(formatMultilineCommand(command, cmdPrefix)))
// Check if command already contains ANSI color codes (pre-colored)
if strings.Contains(command, "\033[") {
_, _ = fmt.Fprintf(os.Stdout, " %s %s\n", cmdPrefix, command)
} else {
_, _ = fmt.Fprintf(os.Stdout, " %s\n", HiGreen(formatMultilineCommand(command, cmdPrefix)))
}
}
}
@@ -383,9 +388,18 @@ func (p *Printer) VerboseOutput(output string) {
if output == "" {
return
}
// Trim whitespace from output
output = strings.TrimSpace(output)
if output == "" {
return // Don't print [output] if nothing to show
}
_, _ = fmt.Fprintf(os.Stdout, " %s\n", Gray("[output]"))
lines := strings.Split(strings.TrimSuffix(output, "\n"), "\n")
lines := strings.Split(output, "\n")
for _, line := range lines {
// Skip blank lines
if strings.TrimSpace(line) == "" {
continue
}
_, _ = fmt.Fprintf(os.Stdout, " %s\n", line)
}
}
+6 -1
View File
@@ -18,6 +18,7 @@ const (
// Step type and runner symbols
SymbolFunction = "ƒ" // Function step
SymbolBash = "$" // Bash/command step
SymbolForeach = "∀" // Foreach step (universal quantifier)
SymbolDocker = "🐋" // Docker runner
SymbolSSH = "❄" // SSH runner
@@ -146,7 +147,9 @@ func StepTypeSymbol(stepType, runnerType string) string {
return Cyan(SymbolFunction)
case "remote-bash":
return Cyan(SymbolSSH)
case "bash", "parallel-steps", "foreach":
case "foreach":
return Cyan(SymbolForeach)
case "bash", "parallel-steps":
return Green(SymbolBash)
default:
return Green(SymbolBash)
@@ -160,6 +163,8 @@ func StepCommandPrefix(stepType string) string {
return SymbolBowtie // "⋈"
case "function":
return SymbolFunction // "ƒ"
case "foreach":
return SymbolForeach // "∀"
default:
return SymbolBash // "$"
}
+8
View File
@@ -303,6 +303,14 @@ func executeFunctionForTarget(printer *terminal.Printer, script, target string)
cfg := config.Get()
ctx := executor.BuildBuiltinVariables(cfg, params)
// Defer temp directory cleanup
if tempDir, ok := ctx["TempDir"].(string); ok && tempDir != "" {
defer func() {
_ = os.RemoveAll(tempDir)
}()
}
if target != "" {
ctx["target"] = target
}
+49 -4
View File
@@ -13,6 +13,7 @@ import (
"github.com/j3ssie/osmedeus/v5/internal/config"
"github.com/j3ssie/osmedeus/v5/internal/core"
"github.com/j3ssie/osmedeus/v5/internal/installer"
"github.com/j3ssie/osmedeus/v5/internal/parser"
"github.com/j3ssie/osmedeus/v5/internal/terminal"
"github.com/j3ssie/osmedeus/v5/public"
"github.com/spf13/cobra"
@@ -61,7 +62,7 @@ var installWorkflowCmd = &cobra.Command{
}
return cobra.ExactArgs(1)(cmd, args)
},
RunE: runInstallWorkflow,
RunE: RunInstallWorkflow,
}
// installBaseCmd installs the base folder from a source
@@ -141,7 +142,8 @@ This is the primary command for health checks. 'osmedeus health' is an alias for
RunE: runInstallValidate,
}
func runInstallWorkflow(cmd *cobra.Command, args []string) error {
// RunInstallWorkflow installs workflows from a source (exported for use by workflow install alias)
func RunInstallWorkflow(cmd *cobra.Command, args []string) error {
cfg := config.Get()
if cfg == nil {
return fmt.Errorf("configuration not loaded")
@@ -183,11 +185,40 @@ func runInstallWorkflow(cmd *cobra.Command, args []string) error {
printer.Println(" %s %s", terminal.SymbolBullet, terminal.Gray(workflowURL))
}
return inst.InstallWorkflow(workflowURL)
if err := inst.InstallWorkflow(workflowURL); err != nil {
return err
}
printWorkflowSummary(printer, cfg.WorkflowsPath)
return nil
}
source := args[0]
return inst.InstallWorkflow(source)
if err := inst.InstallWorkflow(source); err != nil {
return err
}
printWorkflowSummary(printer, cfg.WorkflowsPath)
return nil
}
// printWorkflowSummary counts and prints the number of workflows loaded
func printWorkflowSummary(printer *terminal.Printer, workflowsPath string) {
loader := parser.NewLoader(workflowsPath)
flows, flowErr := loader.ListFlows()
modules, modErr := loader.ListModules()
if flowErr == nil && modErr == nil {
total := len(flows) + len(modules)
if total > 0 {
printer.Info("Loaded %s workflows (%s flows, %s modules)",
terminal.Green(fmt.Sprintf("%d", total)),
terminal.Cyan(fmt.Sprintf("%d", len(flows))),
terminal.Yellow(fmt.Sprintf("%d", len(modules))))
printer.Println(" %s Run %s to see workflow details",
terminal.Gray(terminal.SymbolLightning),
terminal.Cyan("osmedeus workflow ls"))
}
}
}
func runInstallBase(cmd *cobra.Command, args []string) error {
@@ -261,6 +292,7 @@ func runInstallBase(cmd *cobra.Command, args []string) error {
// Continue - workflow installation failure shouldn't block base setup
} else {
printer.Success("Workflows installed from: %s", terminal.Cyan(workflowURL))
printWorkflowSummary(printer, cfg.WorkflowsPath)
}
printer.Newline()
@@ -306,6 +338,19 @@ func runInstallBase(cmd *cobra.Command, args []string) error {
return err
}
// Reload config to get updated paths after base installation
reloaded, err := config.Load(cfg.BaseFolder)
if err == nil {
config.Set(reloaded)
cfg = reloaded
if reloaded.BinariesPath != "" {
binariesFolder = reloaded.BinariesPath
}
}
// Check if workflows folder exists under the base folder and print stats
printWorkflowSummary(printer, cfg.WorkflowsPath)
ensureBinariesPathInEnv(printer, binariesFolder, true)
return nil
}
+28 -2
View File
@@ -170,25 +170,51 @@ func captureExplicitFlags(cmd *cobra.Command) {
// Returns true if empty_target preference is set to true, false otherwise
// Note: This cannot work for stdin modules (--std-module) since stdin would be consumed
func getWorkflowEmptyTargetPreference(cfg *config.Config) bool {
log := logger.Get()
if flowName == "" && len(moduleNames) == 0 {
log.Debug("getWorkflowEmptyTargetPreference: no flow or module specified")
return false
}
loader := parser.NewLoader(cfg.WorkflowsPath)
var workflow *core.Workflow
var err error
var workflowName string
if flowName != "" {
workflowName = flowName
workflow, err = loader.LoadWorkflow(flowName)
} else if len(moduleNames) > 0 {
workflowName = moduleNames[0]
workflow, err = loader.LoadWorkflow(moduleNames[0])
}
if err != nil || workflow == nil || workflow.Preferences == nil {
if err != nil {
log.Debug("getWorkflowEmptyTargetPreference: failed to load workflow",
zap.String("workflow", workflowName),
zap.Error(err))
return false
}
return workflow.Preferences.GetEmptyTarget(false)
if workflow == nil {
log.Debug("getWorkflowEmptyTargetPreference: workflow is nil",
zap.String("workflow", workflowName))
return false
}
if workflow.Preferences == nil {
log.Debug("getWorkflowEmptyTargetPreference: workflow has no preferences",
zap.String("workflow", workflowName))
return false
}
result := workflow.Preferences.GetEmptyTarget(false)
log.Debug("getWorkflowEmptyTargetPreference: checked preference",
zap.String("workflow", workflowName),
zap.Bool("empty_target", result))
return result
}
// applyWorkflowPreferences applies workflow preferences to CLI variables
+19
View File
@@ -1134,6 +1134,23 @@ var workflowShowCmd = &cobra.Command{
},
}
// workflowInstallCmd installs workflows from a source (alias for install workflow)
var workflowInstallCmd = &cobra.Command{
Use: "install [source]",
Short: "Install workflows from git URL, zip URL, local zip file, or local folder",
Long: `Install workflows from various sources. This is an alias for 'osmedeus install workflow'.`,
Args: func(cmd *cobra.Command, args []string) error {
if workflowPreset {
if len(args) != 0 {
return fmt.Errorf("no source argument is allowed with --preset")
}
return nil
}
return cobra.ExactArgs(1)(cmd, args)
},
RunE: RunInstallWorkflow,
}
// workflowValidateCmd validates a workflow
var workflowValidateCmd = &cobra.Command{
Use: "validate [name|path|folder]",
@@ -1211,9 +1228,11 @@ func init() {
workflowValidateCmd.Flags().StringVar(&lintFormat, "format", "pretty", "output format: pretty, json, github")
workflowValidateCmd.Flags().StringSliceVar(&lintDisable, "disable", []string{}, "disable specific rules (comma-separated)")
workflowValidateCmd.Flags().StringVar(&lintSeverity, "severity", "info", "minimum severity level: info, warning, error")
workflowInstallCmd.Flags().BoolVar(&workflowPreset, "preset", false, "install from OSM_WORKFLOW_URL environment variable (default: DEFAULT_WORKFLOW_REPO)")
workflowCmd.AddCommand(workflowListCmd)
workflowCmd.AddCommand(workflowShowCmd)
workflowCmd.AddCommand(workflowValidateCmd)
workflowCmd.AddCommand(workflowInstallCmd)
}
// hasMatchingTags checks if a workflow has any of the specified tags
@@ -1,5 +1,5 @@
{
"_last_update_at": "2026-01-21T10:08:20.876322+00:00",
"_last_update_at": "2026-02-01T03:52:26.051205+00:00",
"amass": {
"desc": "In-depth attack surface mapping and asset discovery",
"repo_link": "https://github.com/owasp-amass/amass",
@@ -42,9 +42,9 @@
}
},
"dnsx": {
"desc": "fast and multi-purpose DNS toolkit allow to run multiple DNS queries of your choice with a list of user-supplied resolvers",
"desc": "dnsx is a fast and multi-purpose DNS toolkit allow to run multiple DNS queries of your choice with a list of user-supplied resolvers.",
"repo_link": "https://github.com/projectdiscovery/dnsx",
"version": "1.2.2",
"version": "1.2.3",
"package-manager": "github-release",
"tags": [
"recon",
@@ -54,12 +54,12 @@
],
"valide-command": "",
"linux": {
"amd64": "https://github.com/projectdiscovery/dnsx/releases/download/v1.2.2/dnsx_1.2.2_linux_amd64.zip",
"arm64": "https://github.com/projectdiscovery/dnsx/releases/download/v1.2.2/dnsx_1.2.2_linux_arm64.zip"
"amd64": "https://github.com/projectdiscovery/dnsx/releases/download/v1.2.3/dnsx_1.2.3_linux_amd64.zip",
"arm64": "https://github.com/projectdiscovery/dnsx/releases/download/v1.2.3/dnsx_1.2.3_linux_arm64.zip"
},
"darwin": {
"amd64": "https://github.com/projectdiscovery/dnsx/releases/download/v1.2.2/dnsx_1.2.2_macOS_amd64.zip",
"arm64": "https://github.com/projectdiscovery/dnsx/releases/download/v1.2.2/dnsx_1.2.2_macOS_arm64.zip"
"amd64": "https://github.com/projectdiscovery/dnsx/releases/download/v1.2.3/dnsx_1.2.3_macOS_amd64.zip",
"arm64": "https://github.com/projectdiscovery/dnsx/releases/download/v1.2.3/dnsx_1.2.3_macOS_arm64.zip"
}
},
"assetfinder": {
@@ -84,7 +84,7 @@
"nuclei": {
"desc": "Nuclei is a fast, customizable vulnerability scanner powered by the global security community and built on a simple YAML-based DSL, enabling collaboration to tackle trending vulnerabilities on the internet. It helps you find vulnerabilities in your applications, APIs, networks, DNS, and cloud configurations.",
"repo_link": "https://github.com/projectdiscovery/nuclei",
"version": "3.6.2",
"version": "3.7.0",
"package-manager": "github-release",
"tags": [
"vulnerability-scanner",
@@ -93,12 +93,12 @@
],
"valide-command": "",
"linux": {
"amd64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.6.2/nuclei_3.6.2_linux_amd64.zip",
"arm64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.6.2/nuclei_3.6.2_linux_arm64.zip"
"amd64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.7.0/nuclei_3.7.0_linux_amd64.zip",
"arm64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.7.0/nuclei_3.7.0_linux_arm64.zip"
},
"darwin": {
"amd64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.6.2/nuclei_3.6.2_macOS_amd64.zip",
"arm64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.6.2/nuclei_3.6.2_macOS_arm64.zip"
"amd64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.7.0/nuclei_3.7.0_macOS_amd64.zip",
"arm64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.7.0/nuclei_3.7.0_macOS_arm64.zip"
}
},
"nuclei-templates": {
@@ -122,7 +122,7 @@
"httpx": {
"desc": "httpx is a fast and multi-purpose HTTP toolkit that allows running multiple probes using the retryablehttp library.",
"repo_link": "https://github.com/projectdiscovery/httpx",
"version": "1.7.4",
"version": "1.8.1",
"package-manager": "github-release",
"tags": [
"recon",
@@ -132,12 +132,12 @@
],
"valide-command": "",
"linux": {
"amd64": "https://github.com/projectdiscovery/httpx/releases/download/v1.7.4/httpx_1.7.4_linux_amd64.zip",
"arm64": "https://github.com/projectdiscovery/httpx/releases/download/v1.7.4/httpx_1.7.4_linux_arm64.zip"
"amd64": "https://github.com/projectdiscovery/httpx/releases/download/v1.8.1/httpx_1.8.1_linux_amd64.zip",
"arm64": "https://github.com/projectdiscovery/httpx/releases/download/v1.8.1/httpx_1.8.1_linux_arm64.zip"
},
"darwin": {
"amd64": "https://github.com/projectdiscovery/httpx/releases/download/v1.7.4/httpx_1.7.4_macOS_amd64.zip",
"arm64": "https://github.com/projectdiscovery/httpx/releases/download/v1.7.4/httpx_1.7.4_macOS_arm64.zip"
"amd64": "https://github.com/projectdiscovery/httpx/releases/download/v1.8.1/httpx_1.8.1_macOS_amd64.zip",
"arm64": "https://github.com/projectdiscovery/httpx/releases/download/v1.8.1/httpx_1.8.1_macOS_arm64.zip"
}
},
"katana": {
@@ -164,7 +164,7 @@
"naabu": {
"desc": "A fast port scanner written in go with a focus on reliability and simplicity. Designed to be used in combination with other tools for attack surface discovery in bug bounties and pentests",
"repo_link": "https://github.com/projectdiscovery/naabu",
"version": "2.3.7",
"version": "2.4.0",
"package-manager": "github-release",
"tags": [
"port-scanner",
@@ -173,12 +173,12 @@
],
"valide-command": "",
"linux": {
"amd64": "https://github.com/projectdiscovery/naabu/releases/download/v2.3.7/naabu_2.3.7_linux_amd64.zip",
"arm64": "https://github.com/projectdiscovery/naabu/releases/download/v2.3.7/naabu_2.3.7_linux_arm64.zip"
"amd64": "https://github.com/projectdiscovery/naabu/releases/download/v2.4.0/naabu_2.4.0_linux_amd64.zip",
"arm64": "https://github.com/projectdiscovery/naabu/releases/download/v2.4.0/naabu_2.4.0_linux_arm64.zip"
},
"darwin": {
"amd64": "https://github.com/projectdiscovery/naabu/releases/download/v2.3.7/naabu_2.3.7_macOS_amd64.zip",
"arm64": "https://github.com/projectdiscovery/naabu/releases/download/v2.3.7/naabu_2.3.7_macOS_arm64.zip"
"amd64": "https://github.com/projectdiscovery/naabu/releases/download/v2.4.0/naabu_2.4.0_macOS_amd64.zip",
"arm64": "https://github.com/projectdiscovery/naabu/releases/download/v2.4.0/naabu_2.4.0_macOS_arm64.zip"
}
},
"ffuf": {
@@ -223,6 +223,27 @@
"arm64": "https://github.com/trufflesecurity/trufflehog/releases/download/v3.90.3/trufflehog_3.90.3_darwin_arm64.tar.gz"
}
},
"kingfisher": {
"desc": "Kingfisher is a blazingly fast and highly accurate tool for secret detection and live validation across files, Git repos, GitHub, GitLab, Azure Repos, BitBucket, Gitea, AWS S3, Docker images, Jira, Slack, and Confluence",
"repo_link": "https://github.com/mongodb/kingfisher",
"version": "1.76.0",
"package-manager": "github-release",
"tags": [
"secret-detection",
"security",
"scanning",
"credentials"
],
"valide-command": "",
"linux": {
"amd64": "https://github.com/mongodb/kingfisher/releases/download/v1.76.0/kingfisher-linux-x64.tgz",
"arm64": "https://github.com/mongodb/kingfisher/releases/download/v1.76.0/kingfisher-linux-arm64.tgz"
},
"darwin": {
"amd64": "https://github.com/mongodb/kingfisher/releases/download/v1.76.0/kingfisher-darwin-x64.tgz",
"arm64": "https://github.com/mongodb/kingfisher/releases/download/v1.76.0/kingfisher-darwin-arm64.tgz"
}
},
"semgrep": {
"desc": "Static analysis tool for code scanning",
"repo_link": "https://github.com/returntocorp/semgrep",
@@ -271,7 +292,8 @@
"tags": [
"utility",
"file-transfer",
"sync"
"sync",
"optional"
],
"valide-command": "",
"multi-commands-linux": [
@@ -519,7 +541,7 @@
}
},
"puredns": {
"desc": "Fast domain resolver and subdomain bruteforcing tool with accurate wildcard filtering",
"desc": "Puredns is a fast domain resolver and subdomain bruteforcing tool that can accurately filter out wildcard subdomains and DNS poisoned entries.",
"repo_link": "https://github.com/d3mondev/puredns",
"version": "2.1.1",
"package-manager": "github-release",
@@ -703,7 +725,7 @@
"trivy": {
"desc": "Find vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more",
"repo_link": "https://github.com/aquasecurity/trivy",
"version": "0.68.2",
"version": "0.69.0",
"package-manager": "github-release",
"tags": [
"vulnerability-scanner",
@@ -793,7 +815,7 @@
"interactsh": {
"desc": "An OOB interaction gathering server and client library",
"repo_link": "https://github.com/projectdiscovery/interactsh",
"version": "1.2.4",
"version": "1.3.0",
"package-manager": "go-getter",
"tags": [
"oob-testing",