mirror of
https://github.com/GH05TCREW/pentestagent.git
synced 2026-03-07 14:23:20 +00:00
chore(mcp): disable MCP auto-start and auto-connect; document manual install
This commit is contained in:
33
PR_BODY.txt
Normal file
33
PR_BODY.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
Summary:
|
||||
Fixes runtime and UX bugs that prevented tool execution and caused inconsistent target selection in the TUI. Improves robustness across Textual versions and makes the target visible and authoritative to the LLM.
|
||||
|
||||
What was broken:
|
||||
- TypeError when scheduling Textual workers: asyncio.create_task was given a Textual Worker (not a coroutine).
|
||||
- LLM-generated flags-only terminal commands (e.g. -p 1-1024 ...) were passed to /bin/sh and caused '/bin/sh: Illegal option -'.
|
||||
- Active workspace scope checks blocked scans when the target was not in the workspace, while stale/manual targets could persist in conversation and be used by the LLM.
|
||||
- UI errors on some Textual versions from calling unsupported APIs (e.g. ScrollableContainer.mount_before), and duplicated in-chat target messages cluttered the chat.
|
||||
|
||||
What I changed (key files):
|
||||
- pentestagent/interface/tui.py
|
||||
- Stop wrapping @work-decorated methods with asyncio.create_task; use the returned Worker correctly.
|
||||
- Ensure workspace activation/deactivation behavior: clear TUI/agent target on /workspace clear; restore last_target on activation.
|
||||
- When operator sets a manual target (/target), append a short system AgentMessage so the LLM sees the change; track manual target and remove/supersede it when a workspace restores its saved target.
|
||||
- Add a persistent header widget to display runtime/mode/target and remove duplicate in-chat target lines.
|
||||
- Guard mount_before calls with a try/fallback to mount to support Textual versions without mount_before.
|
||||
- pentestagent/agents/base_agent.py
|
||||
- If a requested tool name is not found, fall back to the terminal tool and construct a best-effort command string from function-call arguments so semantic tool names (e.g., nmap) execute.
|
||||
- Preserve workspace-scope validation but return explicit errors that instruct the operator how to proceed.
|
||||
- pentestagent/tools/terminal/__init__.py
|
||||
- Detect flags-only command strings and prefix them with a likely binary (nmap, gobuster, rustscan, masscan, curl, wget, etc.) using runtime-detected tools, preventing shell option errors.
|
||||
- Make terminal execution tolerant to malformed inputs and avoid uncaught exceptions.
|
||||
|
||||
Rationale:
|
||||
Textual workers are Worker objects; scheduling them as coroutines caused runtime errors. Handling Worker objects correctly preserves Textual semantics. LLMs sometimes emit partial or semantic commands; best-effort normalization reduces shell failures and improves task success. Explicit system messages and deterministic workspace restores ensure the LLM uses the intended target. A persistent header provides immediate operator context and avoids losing the active target when the chat scrolls.
|
||||
|
||||
Testing performed:
|
||||
- Reproduced and fixed the Worker scheduling TypeError.
|
||||
- Verified flags-only commands are now prefixed (nmap test) and no longer produce '/bin/sh: Illegal option -'.
|
||||
- Walked through workspace/target flows to confirm authoritative target behavior.
|
||||
- Confirmed mount_before fallback avoids AttributeError on older Textual versions.
|
||||
|
||||
Branch: changes pushed to giveen/bug-fix.
|
||||
12
README.md
12
README.md
@@ -146,7 +146,11 @@ PentestAgent includes built-in tools and supports MCP (Model Context Protocol) f
|
||||
|
||||
### MCP Integration
|
||||
|
||||
Add external tools via MCP servers in `pentestagent/mcp/mcp_servers.json`:
|
||||
PentestAgent supports MCP (Model Context Protocol) servers, but automatic
|
||||
installation and auto-start of vendored MCP adapters has been removed. Operators
|
||||
should run the installers and setup scripts under `third_party/` manually and
|
||||
then configure `mcp_servers.json` for any MCP servers they intend to use. Example
|
||||
config (place under `mcp_servers.json`):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -217,7 +221,7 @@ This branch vendors an optional integration with HexStrike (a powerful MCP-enabl
|
||||
|
||||
Special thanks and credit to the HexStrike project and its author: https://github.com/0x4m4/hexstrike-ai
|
||||
|
||||
Notes:
|
||||
- HexStrike is vendored under `third_party/hexstrike` and is opt-in; follow `scripts/install_hexstrike_deps.sh` to install its Python dependencies.
|
||||
- Auto-start of the vendored HexStrike adapter is controlled via the `.env` flag `LAUNCH_HEXTRIKE` and can be enabled per-user.
|
||||
- Notes:
|
||||
- HexStrike is vendored under `third_party/hexstrike` and is opt-in; follow `scripts/install_hexstrike_deps.sh` or the vendor README to install its dependencies and start the service manually.
|
||||
- Automatic background install/start of vendored MCP adapters has been removed; operators should use the provided third-party scripts and then update `mcp_servers.json`.
|
||||
- This update also includes several TUI fixes (improved background worker handling and safer task cancellation) to stabilize the terminal UI while using long-running MCP tools.
|
||||
|
||||
@@ -88,23 +88,12 @@ async def run_cli(
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Initialize MCP if config exists (silently skip failures)
|
||||
# MCP auto-connect/install has been disabled. Operators should run the
|
||||
# installation scripts under `third_party/` manually and configure
|
||||
# `mcp_servers.json` for any MCP servers they intend to use. No automatic
|
||||
# background installs or starts will be performed by the CLI.
|
||||
mcp_manager = None
|
||||
mcp_count = 0
|
||||
try:
|
||||
from ..mcp import MCPManager
|
||||
from ..tools import register_tool_instance
|
||||
|
||||
mcp_manager = MCPManager()
|
||||
if mcp_manager.config_path.exists():
|
||||
mcp_tools = await mcp_manager.connect_all()
|
||||
for tool in mcp_tools:
|
||||
register_tool_instance(tool)
|
||||
mcp_count = len(mcp_tools)
|
||||
if mcp_count > 0:
|
||||
console.print(f"[{PA_DIM}]Loaded {mcp_count} MCP tools[/]")
|
||||
except Exception:
|
||||
pass # MCP is optional, continue without it
|
||||
|
||||
# Initialize runtime - Docker or Local
|
||||
if use_docker:
|
||||
|
||||
@@ -1313,24 +1313,13 @@ class PentestAgentTUI(App):
|
||||
self._add_system(f"[!] RAG: {e}")
|
||||
self.rag_engine = None
|
||||
|
||||
# MCP - auto-load only if enabled in environment
|
||||
# MCP: automatic install/start has been removed. Operators should
|
||||
# run the scripts in `third_party/` manually to install and start
|
||||
# any vendored MCP servers (e.g., HexStrike, MetasploitMCP) and
|
||||
# then configure `mcp_servers.json` accordingly. No automatic
|
||||
# background installs or starts will be performed.
|
||||
self.mcp_manager = None
|
||||
mcp_server_count = 0
|
||||
import os
|
||||
launch_hexstrike = os.getenv("LAUNCH_HEXTRIKE", "false").lower() == "true"
|
||||
launch_metasploit = os.getenv("LAUNCH_METASPLOIT_MCP", "false").lower() == "true"
|
||||
if launch_hexstrike or launch_metasploit:
|
||||
try:
|
||||
self.mcp_manager = MCPManager()
|
||||
if self.mcp_manager.config_path.exists():
|
||||
mcp_tools = await self.mcp_manager.connect_all()
|
||||
for tool in mcp_tools:
|
||||
register_tool_instance(tool)
|
||||
mcp_server_count = len(self.mcp_manager.servers)
|
||||
except Exception as e:
|
||||
self._add_system(f"[!] MCP: {e}")
|
||||
else:
|
||||
self.mcp_manager = None
|
||||
mcp_server_count = 0
|
||||
|
||||
# Runtime - Docker or Local
|
||||
if self.use_docker:
|
||||
|
||||
@@ -122,44 +122,13 @@ class MCPManager:
|
||||
# - Metasploit: LAUNCH_METASPLOIT_MCP
|
||||
# If set to a truthy value (1,true,y), force-enable auto-start for matching vendored server.
|
||||
# If set to a falsy value (0,false,n), force-disable auto-start for matching vendored server.
|
||||
def _apply_launch_override(env_names, match_fn):
|
||||
launch_env = None
|
||||
for e in env_names:
|
||||
launch_env = os.environ.get(e)
|
||||
if launch_env is not None:
|
||||
break
|
||||
if launch_env is None:
|
||||
return
|
||||
v = str(launch_env).strip().lower()
|
||||
enable = v in ("1", "true", "yes", "y")
|
||||
disable = v in ("0", "false", "no", "n")
|
||||
|
||||
for name, cfg in servers.items():
|
||||
try:
|
||||
if not match_fn(name, cfg):
|
||||
continue
|
||||
if enable:
|
||||
cfg.start_on_launch = True
|
||||
elif disable:
|
||||
cfg.start_on_launch = False
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# Hexstrike override
|
||||
_apply_launch_override(["LAUNCH_HEXTRIKE", "LAUNCH_HEXSTRIKE"],
|
||||
lambda name, cfg: (
|
||||
(name or "").lower().find("hexstrike") != -1
|
||||
or (cfg.command and "third_party/hexstrike" in str(cfg.command))
|
||||
or any("third_party/hexstrike" in str(a) for a in (cfg.args or []))
|
||||
))
|
||||
|
||||
# Metasploit override
|
||||
_apply_launch_override(["LAUNCH_METASPLOIT_MCP"],
|
||||
lambda name, cfg: (
|
||||
(name or "").lower().find("metasploit") != -1
|
||||
or (cfg.command and "third_party/MetasploitMCP" in str(cfg.command))
|
||||
or any("third_party/MetasploitMCP" in str(a) for a in (cfg.args or []))
|
||||
))
|
||||
# NOTE: Removed automatic LAUNCH_* overrides. MCP vendored adapters and
|
||||
# auto-start behavior is intentionally disabled. MCP servers should be
|
||||
# installed and configured manually via scripts in `third_party/` and
|
||||
# `mcp_servers.json` should be prepared by the operator. Automatic
|
||||
# start-on-launch logic previously controlled by environment variables
|
||||
# is deprecated to simplify setup and avoid unexpected background
|
||||
# processes.
|
||||
|
||||
return servers
|
||||
except json.JSONDecodeError as e:
|
||||
@@ -308,81 +277,12 @@ class MCPManager:
|
||||
|
||||
async def connect_all(self) -> List[Any]:
|
||||
servers_config = self._load_config()
|
||||
# Respect explicit LAUNCH_* env overrides for vendored MCP servers.
|
||||
# If set to a falsy value (0/false/no/n) we will skip connecting to matching vendored servers.
|
||||
launch_hex_env = os.environ.get("LAUNCH_HEXTRIKE") or os.environ.get("LAUNCH_HEXSTRIKE")
|
||||
launch_hex_disabled = False
|
||||
if launch_hex_env is not None:
|
||||
v = str(launch_hex_env).strip().lower()
|
||||
if v in ("0", "false", "no", "n"):
|
||||
launch_hex_disabled = True
|
||||
|
||||
launch_msf_env = os.environ.get("LAUNCH_METASPLOIT_MCP")
|
||||
launch_msf_disabled = False
|
||||
if launch_msf_env is not None:
|
||||
v = str(launch_msf_env).strip().lower()
|
||||
if v in ("0", "false", "no", "n"):
|
||||
launch_msf_disabled = True
|
||||
|
||||
all_tools = []
|
||||
# Connect to any configured servers but DO NOT auto-start vendored adapters.
|
||||
# Operators should install and start vendored MCPs manually (see third_party/).
|
||||
for name, config in servers_config.items():
|
||||
if not config.enabled:
|
||||
continue
|
||||
# If the user explicitly disabled launching HexStrike, skip hexstrike entries entirely
|
||||
lowered = name.lower() if name else ""
|
||||
is_hex = (
|
||||
"hexstrike" in lowered
|
||||
or (config.command and "third_party/hexstrike" in str(config.command))
|
||||
or any("third_party/hexstrike" in str(a) for a in (config.args or []))
|
||||
)
|
||||
if launch_hex_disabled and is_hex:
|
||||
print(f"[MCP] Skipping auto-connection for {name} due to LAUNCH_HEXTRIKE={launch_hex_env}")
|
||||
continue
|
||||
# Optionally auto-start vendored servers (e.g., HexStrike subtree or MetasploitMCP)
|
||||
if getattr(config, "start_on_launch", False):
|
||||
try:
|
||||
args_joined = " ".join(config.args or [])
|
||||
cmd_str = config.command or ""
|
||||
|
||||
# Hexstrike auto-start
|
||||
if "third_party/hexstrike" in args_joined or (cmd_str and "third_party/hexstrike" in cmd_str):
|
||||
if not launch_hex_disabled:
|
||||
try:
|
||||
from .hexstrike_adapter import HexstrikeAdapter
|
||||
|
||||
adapter = HexstrikeAdapter()
|
||||
started = await adapter.start()
|
||||
if started:
|
||||
try:
|
||||
self._started_adapters[name] = adapter
|
||||
except Exception:
|
||||
pass
|
||||
print(f"[MCP] Auto-started vendored server for {name}")
|
||||
except Exception as e:
|
||||
print(f"[MCP] Failed to auto-start vendored server {name}: {e}")
|
||||
else:
|
||||
print(f"[MCP] Skipping auto-start for {name} due to LAUNCH_HEXTRIKE override")
|
||||
|
||||
# Metasploit auto-start
|
||||
if "third_party/MetasploitMCP" in args_joined or (cmd_str and "third_party/MetasploitMCP" in cmd_str) or (name and "metasploit" in name.lower()):
|
||||
if not launch_msf_disabled:
|
||||
try:
|
||||
from .metasploit_adapter import MetasploitAdapter
|
||||
|
||||
adapter = MetasploitAdapter()
|
||||
started = await adapter.start()
|
||||
if started:
|
||||
try:
|
||||
self._started_adapters[name] = adapter
|
||||
except Exception:
|
||||
pass
|
||||
print(f"[MCP] Auto-started vendored server for {name}")
|
||||
except Exception as e:
|
||||
print(f"[MCP] Failed to auto-start vendored server {name}: {e}")
|
||||
else:
|
||||
print(f"[MCP] Skipping auto-start for {name} due to LAUNCH_METASPLOIT_MCP override")
|
||||
except Exception:
|
||||
pass
|
||||
server = await self._connect_server(config)
|
||||
if server:
|
||||
self.servers[name] = server
|
||||
|
||||
@@ -129,71 +129,9 @@ if (Test-Path -Path ".env") {
|
||||
New-Item -ItemType Directory -Force -Path "loot" | Out-Null
|
||||
Write-Host "[OK] Loot directory created"
|
||||
|
||||
# Install vendored HexStrike dependencies automatically if present
|
||||
$hexReq = Join-Path -Path (Get-Location) -ChildPath "third_party/hexstrike/requirements.txt"
|
||||
if (Test-Path -Path $hexReq) {
|
||||
Write-Host "Installing vendored HexStrike dependencies..."
|
||||
try {
|
||||
& .\scripts\install_hexstrike_deps.ps1
|
||||
} catch {
|
||||
Write-Host "Warning: Failed to install HexStrike deps: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
# Attempt to vendor MetasploitMCP via bundled script if not already present
|
||||
$msDir = Join-Path -Path (Get-Location) -ChildPath "third_party/MetasploitMCP"
|
||||
$addScript = Join-Path -Path (Get-Location) -ChildPath "scripts/add_metasploit_subtree.sh"
|
||||
if (-not (Test-Path -Path $msDir) -and (Test-Path -Path $addScript)) {
|
||||
Write-Host "Vendoring MetasploitMCP into third_party (requires bash)..."
|
||||
if (Get-Command bash -ErrorAction SilentlyContinue) {
|
||||
try {
|
||||
& bash -c "scripts/add_metasploit_subtree.sh"
|
||||
} catch {
|
||||
Write-Host "Warning: Failed to vendor MetasploitMCP via bash: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
}
|
||||
} else {
|
||||
Write-Host "Warning: 'bash' not available; please run scripts/add_metasploit_subtree.sh manually." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
# Install vendored MetasploitMCP dependencies automatically if present
|
||||
$msReq = Join-Path -Path (Get-Location) -ChildPath "third_party/MetasploitMCP/requirements.txt"
|
||||
$installMsScript = Join-Path -Path (Get-Location) -ChildPath "scripts/install_metasploit_deps.sh"
|
||||
if (Test-Path -Path $msReq) {
|
||||
Write-Host "Installing vendored MetasploitMCP dependencies..."
|
||||
if (Test-Path -Path $installMsScript -and (Get-Command bash -ErrorAction SilentlyContinue)) {
|
||||
try {
|
||||
& bash -c "scripts/install_metasploit_deps.sh"
|
||||
} catch {
|
||||
Write-Host "Warning: Failed to install MetasploitMCP deps via bash: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
}
|
||||
} else {
|
||||
Write-Host "Warning: Could not run install script automatically; run scripts/install_metasploit_deps.sh manually." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
# Optionally auto-start msfrpcd if configured in .env
|
||||
if (($env:LAUNCH_METASPLOIT_MCP -eq 'true') -and ($env:MSF_PASSWORD)) {
|
||||
$msfUser = if ($env:MSF_USER) { $env:MSF_USER } else { 'msf' }
|
||||
$msfServer = if ($env:MSF_SERVER) { $env:MSF_SERVER } else { '127.0.0.1' }
|
||||
$msfPort = if ($env:MSF_PORT) { $env:MSF_PORT } else { '55553' }
|
||||
Write-Host "Starting msfrpcd (user=$msfUser, host=$msfServer, port=$msfPort) without sudo (background)..."
|
||||
# Start msfrpcd without sudo; if it's already running the cmd will fail harmlessly.
|
||||
if (Get-Command msfrpcd -ErrorAction SilentlyContinue) {
|
||||
try {
|
||||
if ($env:MSF_SSL -eq 'true' -or $env:MSF_SSL -eq '1') {
|
||||
Start-Process -FilePath msfrpcd -ArgumentList "-U", $msfUser, "-P", $env:MSF_PASSWORD, "-a", $msfServer, "-p", $msfPort, "-S" -NoNewWindow -WindowStyle Hidden
|
||||
} else {
|
||||
Start-Process -FilePath msfrpcd -ArgumentList "-U", $msfUser, "-P", $env:MSF_PASSWORD, "-a", $msfServer, "-p", $msfPort -NoNewWindow -WindowStyle Hidden
|
||||
}
|
||||
Write-Host "msfrpcd start requested; check with: netstat -an | Select-String $msfPort"
|
||||
} catch {
|
||||
Write-Host "Warning: Failed to start msfrpcd: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
}
|
||||
} else {
|
||||
Write-Host "msfrpcd not found; please install Metasploit Framework to enable Metasploit RPC." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
# NOTE: Automatic vendored MCP installation/start has been removed.
|
||||
# Operators should run `scripts/*` helpers manually when they want to
|
||||
# install or vendor third-party MCP adapters and their dependencies.
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Setup complete!"
|
||||
|
||||
@@ -120,64 +120,15 @@ fi
|
||||
mkdir -p loot
|
||||
echo "[OK] Loot directory created"
|
||||
|
||||
# Install vendored HexStrike dependencies automatically if present
|
||||
if [ -f "third_party/hexstrike/requirements.txt" ]; then
|
||||
echo "Installing vendored HexStrike dependencies..."
|
||||
bash scripts/install_hexstrike_deps.sh
|
||||
fi
|
||||
|
||||
# Vendor MetasploitMCP via git-subtree if not already vendored
|
||||
if [ ! -d "third_party/MetasploitMCP" ] && [ -f "scripts/add_metasploit_subtree.sh" ]; then
|
||||
echo "Vendoring MetasploitMCP into third_party..."
|
||||
bash scripts/add_metasploit_subtree.sh || echo "Warning: failed to vendor MetasploitMCP; you can run scripts/add_metasploit_subtree.sh manually."
|
||||
fi
|
||||
|
||||
# Install vendored MetasploitMCP dependencies automatically if present
|
||||
if [ -f "third_party/MetasploitMCP/requirements.txt" ]; then
|
||||
echo "Installing vendored MetasploitMCP dependencies..."
|
||||
bash scripts/install_metasploit_deps.sh || echo "Warning: failed to install MetasploitMCP dependencies."
|
||||
fi
|
||||
|
||||
# Optionally auto-start Metasploit RPC daemon if configured
|
||||
# Start `msfrpcd` without sudo if LAUNCH_METASPLOIT_MCP=true and MSF_PASSWORD is set.
|
||||
if [ "${LAUNCH_METASPLOIT_MCP,,}" = "true" ] && [ -n "${MSF_PASSWORD:-}" ]; then
|
||||
if command -v msfrpcd >/dev/null 2>&1; then
|
||||
MSF_USER="${MSF_USER:-msf}"
|
||||
MSF_SERVER="${MSF_SERVER:-127.0.0.1}"
|
||||
MSF_PORT="${MSF_PORT:-55553}"
|
||||
MSF_SSL="${MSF_SSL:-false}"
|
||||
echo "Starting msfrpcd (user=${MSF_USER}, host=${MSF_SERVER}, port=${MSF_PORT})..."
|
||||
# Start msfrpcd as a background process without sudo. The daemon will bind to the loopback
|
||||
# interface and does not require root privileges on modern systems for ephemeral ports.
|
||||
msfrpcd_cmd=$(command -v msfrpcd || true)
|
||||
if [ -n "$msfrpcd_cmd" ]; then
|
||||
LOG_DIR="loot/artifacts"
|
||||
mkdir -p "$LOG_DIR"
|
||||
MSF_LOG="$LOG_DIR/metasploit_msfrpcd.log"
|
||||
# For safety, bind msfrpcd to loopback by default. To intentionally expose RPC to the host
|
||||
# set EXPOSE_MSF_RPC=true in your environment (not recommended on shared hosts).
|
||||
if [ "${EXPOSE_MSF_RPC,,}" != "true" ]; then
|
||||
if [ "$MSF_SERVER" != "127.0.0.1" ] && [ "$MSF_SERVER" != "localhost" ]; then
|
||||
echo "Warning: MSF_SERVER is set to '$MSF_SERVER' but EXPOSE_MSF_RPC is not true. Overriding to 127.0.0.1 for safety."
|
||||
fi
|
||||
MSF_SERVER=127.0.0.1
|
||||
else
|
||||
echo "EXPOSE_MSF_RPC=true: msfrpcd will bind to $MSF_SERVER and may be reachable from the host network. Ensure you know the risks."
|
||||
fi
|
||||
|
||||
if [ "${MSF_SSL,,}" = "true" ] || [ "${MSF_SSL}" = "1" ]; then
|
||||
"$msfrpcd_cmd" -U "$MSF_USER" -P "$MSF_PASSWORD" -a "$MSF_SERVER" -p "$MSF_PORT" -S >"$MSF_LOG" 2>&1 &
|
||||
else
|
||||
"$msfrpcd_cmd" -U "$MSF_USER" -P "$MSF_PASSWORD" -a "$MSF_SERVER" -p "$MSF_PORT" >"$MSF_LOG" 2>&1 &
|
||||
fi
|
||||
echo "msfrpcd started (logs: $MSF_LOG)"
|
||||
else
|
||||
echo "msfrpcd not found; please install Metasploit Framework to enable Metasploit RPC."
|
||||
fi
|
||||
else
|
||||
echo "msfrpcd not found; please install Metasploit Framework to enable Metasploit RPC."
|
||||
fi
|
||||
fi
|
||||
# NOTE: Automatic vendored MCP installation/start has been removed.
|
||||
# If you need vendored MCP servers (e.g., HexStrike, MetasploitMCP), run
|
||||
# the helper scripts under `third_party/` or the `scripts/` helpers manually.
|
||||
# Example manual steps:
|
||||
# bash scripts/install_hexstrike_deps.sh
|
||||
# bash scripts/add_metasploit_subtree.sh
|
||||
# bash scripts/install_metasploit_deps.sh
|
||||
# Starting msfrpcd or other networked services should be done explicitly by
|
||||
# the operator in a controlled environment.
|
||||
|
||||
echo ""
|
||||
echo "=================================================================="
|
||||
|
||||
Reference in New Issue
Block a user