Merge pull request #18 from giveen/docker/mcp-docker-changes

docker: improve safety, UX, and Metasploit MCP defaults
This commit is contained in:
Masic
2026-01-15 18:05:31 -07:00
committed by GitHub
6 changed files with 81 additions and 16 deletions

17
.dockerignore Normal file
View File

@@ -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

View File

@@ -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:

View File

@@ -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}"

View File

@@ -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

View File

@@ -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),

View File

@@ -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