From 36350775f99baa143aa8ca4682f356c636e0ee59 Mon Sep 17 00:00:00 2001 From: giveen Date: Thu, 15 Jan 2026 08:56:49 -0700 Subject: [PATCH 1/2] docker: improve safety, UX, and Metasploit MCP defaults Why: - Persist artifacts to /app/loot so container outputs remain available when mounted. - Avoid mandatory host chown; make chown opt-in via CHOWN_ON_START to prevent accidental ownership changes. - Bind msfrpcd to 127.0.0.1 by default and add EXPOSE_MSF_RPC opt-in to avoid exposing RPC to host network. - Replace crashing assertion on missing default model with a friendly CLI/TUI error path. - Add .dockerignore to reduce build context and avoid copying unnecessary files. --- .dockerignore | 17 +++++++ PR_BODY.md | 81 ++++++++++++++++++++++++++++++++++ docker-compose.yml | 5 ++- docker-entrypoint.sh | 37 +++++++++++----- pentestagent/interface/main.py | 9 ++++ pentestagent/interface/tui.py | 18 ++++++-- scripts/setup.sh | 11 +++++ 7 files changed, 162 insertions(+), 16 deletions(-) create mode 100644 .dockerignore create mode 100644 PR_BODY.md diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..987e4a3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,17 @@ +venv +.venv +__pycache__ +*.pyc +.pytest_cache +.mypy_cache +.git +loot +dist +build +*.egg-info +third_party/MetasploitMCP +venv/ +venv/* +.env +runtime/ +/.pytest_cache \ No newline at end of file diff --git a/PR_BODY.md b/PR_BODY.md new file mode 100644 index 0000000..e4e2bd4 --- /dev/null +++ b/PR_BODY.md @@ -0,0 +1,81 @@ +# MCP: Add Metasploit integration, HexStrike parity, auto-start flags and SSETransport improvements + +## Summary +This PR adds a vendored Metasploit MCP integration and brings it to parity with the existing HexStrike MCP integration. It also improves the MCP transport layer (SSE) to reliably handle HTTP/SSE MCP servers that return 202/async responses. + +## Key changes +- Add Metasploit MCP support via a `MetasploitAdapter` that can start/stop the vendored `MetasploitMCP` server and optionally start `msfrpcd` for local testing. +- Make MCP tool registration automatic: MCP tools are discovered and registered at startup so they appear in the TUI `/tools` view. +- Add environment flags to control vendored servers and subtree updates: + - `LAUNCH_HEXTRIKE` / `LAUNCH_HEXSTRIKE` — control HexStrike vendored server auto-start behavior + - `LAUNCH_METASPLOIT_MCP` — control Metasploit vendored server auto-start behavior + - `FORCE_SUBTREE_PULL` — helper for scripts that add/update vendored `third_party` subtrees +- Improve HTTP/SSE transport (`SSETransport`) to: + - Discover the server's POST endpoint announced over `/sse` + - Maintain a persistent SSE listener instead of transient GETs + - Correlate pending requests with SSE-delivered responses (supporting 202 Accepted flows) + - Wait for endpoint discovery on connect to avoid writer races +- Add/update helper scripts (`scripts/add_metasploit_subtree.sh`, `scripts/setup.sh`) to vendor/update the Metasploit subtree and provide optional msfrpcd auto-start during setup. + +## Files touched (high level) +- `pentestagent/mcp/metasploit_adapter.py` — new adapter to manage vendored Metasploit MCP and optional msfrpcd. +- `pentestagent/mcp/transport.py` — SSETransport enhancements and robustness fixes. +- `pentestagent/mcp/manager.py` — LAUNCH env handling, auto-start wiring and connection logic (fixes applied so LAUNCH_* works as expected). +- `pentestagent/mcp/mcp_servers.json` — added/updated `metasploit-local` entry in HexStrike-style (`--server http://...`). +- `.env.example` — grouped MCP settings; documents `FORCE_SUBTREE_PULL` and LAUNCH flags. +- `scripts/add_metasploit_subtree.sh`, `scripts/setup.sh` — vendoring helpers and optional msfrpcd startup. + +(See the full commit set on this branch for exact diffs and additional smaller edits.) + +## Behavior / Usage +- Default: vendored MCP entries are present in `pentestagent/mcp/mcp_servers.json` but not started unless configured. +- To allow PentestAgent to auto-start vendored MCPs at runtime, set the corresponding `LAUNCH_*` environment variable to a truthy value (e.g. `true`, `1`, `yes`): + +```bash +export LAUNCH_METASPLOIT_MCP=true +export LAUNCH_HEXTRIKE=true +pentestagent +``` + +When `LAUNCH_METASPLOIT_MCP` is truthy and the manager is started, the manager will attempt to auto-start the vendored Metasploit adapter and connect to it so its tools are registered automatically. + +If you prefer to run the vendored MCP server manually (recommended for debugging), start it separately and then run PentestAgent/TUI. Example: + +```bash +python third_party/MetasploitMCP/MetasploitMCP.py --server http://127.0.0.1:7777 \ + > loot/artifacts/metasploit_mcp.log 2>&1 & disown +pentestagent mcp test metasploit-local +``` + +## How to test +1. Pull this branch and install dependencies (see `scripts/setup.sh`). +2. Manual test: + - Start msfrpcd (or configure `MSF_*` envs to point to an existing Metasploit RPC) + - Start the vendored MCP server: + + ```bash + python third_party/MetasploitMCP/MetasploitMCP.py --server http://127.0.0.1:7777 + ``` + + - Run the manager test: + + ```bash + pentestagent mcp test metasploit-local + ``` + + - Expected: `+ Connected successfully!` and a list of available Metasploit tools. + +3. Auto-start test: + - Export `LAUNCH_METASPLOIT_MCP=true` and run `pentestagent` (or the TUI). The manager should auto-start the adapter and register tools so they appear in `/tools`. + +## Security / Notes +- Do not commit real passwords or API keys. Use a local `.env` (never committed) to provide secrets like `MSF_PASSWORD`. +- The setup helper that may start `msfrpcd` will never invoke `sudo` — it only starts a local msfrpcd process if credentials are present and auto-start is enabled. + +## Follow-ups / Optional improvements +- Add `scripts/start_metasploit.sh` to start the vendored MCP detached and capture logs (I can add this in a follow-up PR if desired). +- Add a short README section documenting the MCP vendoring workflow and recommended `.env` values for local testing. + +--- + +If you'd like any edits to wording or additional testing instructions, tell me what to change and I will update the PR body. diff --git a/docker-compose.yml b/docker-compose.yml index aa0861e..47c5d9a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,7 +21,7 @@ services: context: . dockerfile: Dockerfile.kali container_name: pentestagent-kali - privileged: true # Required for VPN and some tools + privileged: true # Required for VPN and some tools. NOTE: this is risky on shared hosts; prefer running inside a disposable VM. cap_add: - NET_ADMIN - SYS_ADMIN @@ -31,6 +31,9 @@ services: - PENTESTAGENT_MODEL=${PENTESTAGENT_MODEL} - ENABLE_TOR=${ENABLE_TOR:-false} - INIT_METASPLOIT=${INIT_METASPLOIT:-false} + # By default msfrpcd binds to loopback; to intentionally expose Metasploit RPC to the host + # set EXPOSE_MSF_RPC=true in your environment. This is NOT recommended on shared machines. + - EXPOSE_MSF_RPC=${EXPOSE_MSF_RPC:-false} volumes: - ./loot:/app/loot networks: diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 1373637..a3c1dec 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -11,12 +11,12 @@ NC='\033[0m' echo -e "${GREEN}🔧 PentestAgent Container Starting...${NC}" -# Start VPN if config provided -if [ -f "/vpn/config.ovpn" ]; then +# Start VPN if config provided and openvpn is available +if [ -f "/vpn/config.ovpn" ] && command -v openvpn >/dev/null 2>&1; then echo -e "${YELLOW}📡 Starting VPN connection...${NC}" - openvpn --config /vpn/config.ovpn --daemon + openvpn --config /vpn/config.ovpn --daemon || echo "openvpn failed to start" sleep 5 - + # Check VPN connection if ip a show tun0 &>/dev/null; then echo -e "${GREEN}✅ VPN connected${NC}" @@ -25,22 +25,35 @@ if [ -f "/vpn/config.ovpn" ]; then fi fi -# Start Tor if enabled -if [ "$ENABLE_TOR" = "true" ]; then +# Start Tor if enabled and if a service command is available +if [ "$ENABLE_TOR" = "true" ] && command -v service >/dev/null 2>&1; then echo -e "${YELLOW}🧅 Starting Tor...${NC}" - service tor start + service tor start || echo "tor service not available" sleep 3 fi -# Initialize any databases -if [ "$INIT_METASPLOIT" = "true" ]; then +# Initialize any databases (guarded) +if [ "$INIT_METASPLOIT" = "true" ] && command -v msfdb >/dev/null 2>&1; then echo -e "${YELLOW}🗄️ Initializing Metasploit database...${NC}" - msfdb init 2>/dev/null || true + msfdb init 2>/dev/null || echo "msfdb init failed" fi -# Create output directory with timestamp -OUTPUT_DIR="/output/$(date +%Y%m%d_%H%M%S)" +# Ensure persistent output directory lives under /app/loot (mounted by compose) +OUTPUT_DIR="/app/loot/$(date +%Y%m%d_%H%M%S)" mkdir -p "$OUTPUT_DIR" + +# Optionally chown mounted volume on startup (only when running as root and explicitly enabled) +if [ "$(id -u)" = "0" ] && [ "${CHOWN_ON_START,,}" = "true" ]; then + # If PUID/PGID supplied use them, otherwise keep default permissions + if [ -n "${PUID:-}" ] && [ -n "${PGID:-}" ]; then + groupadd -g ${PGID} pentestagent 2>/dev/null || true + useradd -u ${PUID} -g ${PGID} -m pentestagent 2>/dev/null || true + chown -R ${PUID}:${PGID} /app/loot || true + else + chown -R pentestagent:pentestagent /app/loot 2>/dev/null || true + fi +fi + export PENTESTAGENT_OUTPUT_DIR="$OUTPUT_DIR" echo -e "${GREEN}📁 Output directory: $OUTPUT_DIR${NC}" diff --git a/pentestagent/interface/main.py b/pentestagent/interface/main.py index 51c6564..bc48e2b 100644 --- a/pentestagent/interface/main.py +++ b/pentestagent/interface/main.py @@ -389,6 +389,15 @@ def main(): # If no command provided, default to TUI if args.command is None: + # Ensure a default model is configured; provide a friendly error if not + if not DEFAULT_MODEL: + print("Error: No default model configured (PENTESTAGENT_MODEL).") + print("Set PENTESTAGENT_MODEL in .env file or pass --model on the command line.") + print( + "Example: PENTESTAGENT_MODEL=gpt-5 or PENTESTAGENT_MODEL=claude-sonnet-4-20250514" + ) + return + run_tui(target=None, model=DEFAULT_MODEL, use_docker=False) return diff --git a/pentestagent/interface/tui.py b/pentestagent/interface/tui.py index 19329e1..d7ce51f 100644 --- a/pentestagent/interface/tui.py +++ b/pentestagent/interface/tui.py @@ -1139,9 +1139,21 @@ class PentestAgentTUI(App): await self.runtime.start() # LLM - # Ensure types for static analysis: runtime and model are set - assert self.model is not None - assert self.runtime is not None + # Validate model/runtime presence and provide a user-friendly error + if not self.model: + self._add_system( + "[!] No model configured. Set PENTESTAGENT_MODEL environment variable or create a .env file (see .env.example)." + ) + self._set_status("error") + self._is_initializing = False + return + + if not self.runtime: + self._add_system("[!] Runtime failed to initialize.") + self._set_status("error") + self._is_initializing = False + return + llm = LLM( model=self.model, config=ModelConfig(temperature=0.7), diff --git a/scripts/setup.sh b/scripts/setup.sh index 3dea4bd..82693a8 100644 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -154,6 +154,17 @@ if [ "${LAUNCH_METASPLOIT_MCP,,}" = "true" ] && [ -n "${MSF_PASSWORD:-}" ]; 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 From 0b4047131043c25a94980e74cb69662ad1ef8ae7 Mon Sep 17 00:00:00 2001 From: giveen Date: Thu, 15 Jan 2026 09:01:07 -0700 Subject: [PATCH 2/2] chore: remove PR_BODY.md Why: - PR_BODY.md was added accidentally and should not be tracked. - Keep PR body content local; use GitHub PR UI for composing pull requests. --- PR_BODY.md | 81 ------------------------------------------------------ 1 file changed, 81 deletions(-) delete mode 100644 PR_BODY.md diff --git a/PR_BODY.md b/PR_BODY.md deleted file mode 100644 index e4e2bd4..0000000 --- a/PR_BODY.md +++ /dev/null @@ -1,81 +0,0 @@ -# MCP: Add Metasploit integration, HexStrike parity, auto-start flags and SSETransport improvements - -## Summary -This PR adds a vendored Metasploit MCP integration and brings it to parity with the existing HexStrike MCP integration. It also improves the MCP transport layer (SSE) to reliably handle HTTP/SSE MCP servers that return 202/async responses. - -## Key changes -- Add Metasploit MCP support via a `MetasploitAdapter` that can start/stop the vendored `MetasploitMCP` server and optionally start `msfrpcd` for local testing. -- Make MCP tool registration automatic: MCP tools are discovered and registered at startup so they appear in the TUI `/tools` view. -- Add environment flags to control vendored servers and subtree updates: - - `LAUNCH_HEXTRIKE` / `LAUNCH_HEXSTRIKE` — control HexStrike vendored server auto-start behavior - - `LAUNCH_METASPLOIT_MCP` — control Metasploit vendored server auto-start behavior - - `FORCE_SUBTREE_PULL` — helper for scripts that add/update vendored `third_party` subtrees -- Improve HTTP/SSE transport (`SSETransport`) to: - - Discover the server's POST endpoint announced over `/sse` - - Maintain a persistent SSE listener instead of transient GETs - - Correlate pending requests with SSE-delivered responses (supporting 202 Accepted flows) - - Wait for endpoint discovery on connect to avoid writer races -- Add/update helper scripts (`scripts/add_metasploit_subtree.sh`, `scripts/setup.sh`) to vendor/update the Metasploit subtree and provide optional msfrpcd auto-start during setup. - -## Files touched (high level) -- `pentestagent/mcp/metasploit_adapter.py` — new adapter to manage vendored Metasploit MCP and optional msfrpcd. -- `pentestagent/mcp/transport.py` — SSETransport enhancements and robustness fixes. -- `pentestagent/mcp/manager.py` — LAUNCH env handling, auto-start wiring and connection logic (fixes applied so LAUNCH_* works as expected). -- `pentestagent/mcp/mcp_servers.json` — added/updated `metasploit-local` entry in HexStrike-style (`--server http://...`). -- `.env.example` — grouped MCP settings; documents `FORCE_SUBTREE_PULL` and LAUNCH flags. -- `scripts/add_metasploit_subtree.sh`, `scripts/setup.sh` — vendoring helpers and optional msfrpcd startup. - -(See the full commit set on this branch for exact diffs and additional smaller edits.) - -## Behavior / Usage -- Default: vendored MCP entries are present in `pentestagent/mcp/mcp_servers.json` but not started unless configured. -- To allow PentestAgent to auto-start vendored MCPs at runtime, set the corresponding `LAUNCH_*` environment variable to a truthy value (e.g. `true`, `1`, `yes`): - -```bash -export LAUNCH_METASPLOIT_MCP=true -export LAUNCH_HEXTRIKE=true -pentestagent -``` - -When `LAUNCH_METASPLOIT_MCP` is truthy and the manager is started, the manager will attempt to auto-start the vendored Metasploit adapter and connect to it so its tools are registered automatically. - -If you prefer to run the vendored MCP server manually (recommended for debugging), start it separately and then run PentestAgent/TUI. Example: - -```bash -python third_party/MetasploitMCP/MetasploitMCP.py --server http://127.0.0.1:7777 \ - > loot/artifacts/metasploit_mcp.log 2>&1 & disown -pentestagent mcp test metasploit-local -``` - -## How to test -1. Pull this branch and install dependencies (see `scripts/setup.sh`). -2. Manual test: - - Start msfrpcd (or configure `MSF_*` envs to point to an existing Metasploit RPC) - - Start the vendored MCP server: - - ```bash - python third_party/MetasploitMCP/MetasploitMCP.py --server http://127.0.0.1:7777 - ``` - - - Run the manager test: - - ```bash - pentestagent mcp test metasploit-local - ``` - - - Expected: `+ Connected successfully!` and a list of available Metasploit tools. - -3. Auto-start test: - - Export `LAUNCH_METASPLOIT_MCP=true` and run `pentestagent` (or the TUI). The manager should auto-start the adapter and register tools so they appear in `/tools`. - -## Security / Notes -- Do not commit real passwords or API keys. Use a local `.env` (never committed) to provide secrets like `MSF_PASSWORD`. -- The setup helper that may start `msfrpcd` will never invoke `sudo` — it only starts a local msfrpcd process if credentials are present and auto-start is enabled. - -## Follow-ups / Optional improvements -- Add `scripts/start_metasploit.sh` to start the vendored MCP detached and capture logs (I can add this in a follow-up PR if desired). -- Add a short README section documenting the MCP vendoring workflow and recommended `.env` values for local testing. - ---- - -If you'd like any edits to wording or additional testing instructions, tell me what to change and I will update the PR body.