docs(openclaw): move doc to OPEN_CLAW/ dir, add security validation script
- Move openclaw-personal-ai-assistant.md from windows_specific/ to OPEN_CLAW/
- Add validate-security.sh: cross-platform security scanner with visual output
- 7 check categories: installation, gateway config, file permissions,
network security, API keys, system security, openclaw doctor
- Green ticks (pass), red crosses (fail), yellow warnings
- Numbered recommendations list with fix commands
- Works on macOS, Linux, and WSL2
This commit is contained in:
parent
4dd8003f25
commit
5667308629
487
__LOCAL_LLMs/OPEN_CLAW/validate-security.sh
Executable file
487
__LOCAL_LLMs/OPEN_CLAW/validate-security.sh
Executable file
@ -0,0 +1,487 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# OpenClaw Security Validator
|
||||
# =============================================================================
|
||||
# Run this script AFTER installing OpenClaw to verify your setup is secure.
|
||||
# Works on both macOS and Linux/WSL2.
|
||||
#
|
||||
# Usage:
|
||||
# bash validate-security.sh
|
||||
#
|
||||
# Output:
|
||||
# ✅ = Secure (green)
|
||||
# ❌ = Insecure — action required (red)
|
||||
# ⚠️ = Warning — review recommended (yellow)
|
||||
# ℹ️ = Info (blue)
|
||||
# =============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# --- Colors ---
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
BLUE='\033[0;34m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# --- Counters ---
|
||||
PASS=0
|
||||
FAIL=0
|
||||
WARN=0
|
||||
RECOMMENDATIONS=()
|
||||
|
||||
# --- Helpers ---
|
||||
pass() {
|
||||
echo -e " ${GREEN}✅ $1${NC}"
|
||||
((PASS++))
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo -e " ${RED}❌ $1${NC}"
|
||||
((FAIL++))
|
||||
RECOMMENDATIONS+=("$2")
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e " ${YELLOW}⚠️ $1${NC}"
|
||||
((WARN++))
|
||||
RECOMMENDATIONS+=("$2")
|
||||
}
|
||||
|
||||
info() {
|
||||
echo -e " ${BLUE}ℹ️ $1${NC}"
|
||||
}
|
||||
|
||||
section() {
|
||||
echo ""
|
||||
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${BOLD} $1${NC}"
|
||||
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
}
|
||||
|
||||
# --- Detect OS ---
|
||||
OS="unknown"
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
OS="macos"
|
||||
elif grep -qi microsoft /proc/version 2>/dev/null; then
|
||||
OS="wsl2"
|
||||
elif [[ "$(uname -s)" == "Linux" ]]; then
|
||||
OS="linux"
|
||||
fi
|
||||
|
||||
OPENCLAW_DIR="$HOME/.openclaw"
|
||||
CONFIG_FILE="$OPENCLAW_DIR/config.yaml"
|
||||
|
||||
# =============================================================================
|
||||
echo ""
|
||||
echo -e "${BOLD}🦞 OpenClaw Security Validator${NC}"
|
||||
echo -e " $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
echo -e " Platform: ${BOLD}$OS${NC}"
|
||||
echo ""
|
||||
|
||||
# =============================================================================
|
||||
section "1. OpenClaw Installation"
|
||||
# =============================================================================
|
||||
|
||||
# Check if openclaw is installed
|
||||
if command -v openclaw &>/dev/null; then
|
||||
VERSION=$(openclaw --version 2>/dev/null || echo "unknown")
|
||||
pass "OpenClaw installed: $VERSION"
|
||||
else
|
||||
fail "OpenClaw is NOT installed" \
|
||||
"Install OpenClaw: npm install -g openclaw@latest && openclaw onboard --install-daemon"
|
||||
fi
|
||||
|
||||
# Check Node.js version
|
||||
if command -v node &>/dev/null; then
|
||||
NODE_VER=$(node --version 2>/dev/null | sed 's/v//')
|
||||
NODE_MAJOR=$(echo "$NODE_VER" | cut -d. -f1)
|
||||
if [[ "$NODE_MAJOR" -ge 22 ]]; then
|
||||
pass "Node.js version: v$NODE_VER (>= 22 required)"
|
||||
else
|
||||
fail "Node.js version: v$NODE_VER (NEEDS >= 22)" \
|
||||
"Upgrade Node.js: nvm install 22 && nvm alias default 22"
|
||||
fi
|
||||
else
|
||||
fail "Node.js is NOT installed" \
|
||||
"Install Node.js 22+: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash && nvm install 22"
|
||||
fi
|
||||
|
||||
# Check config exists
|
||||
if [[ -f "$CONFIG_FILE" ]]; then
|
||||
pass "Config file exists: $CONFIG_FILE"
|
||||
else
|
||||
fail "Config file NOT found at $CONFIG_FILE" \
|
||||
"Run: openclaw onboard --install-daemon"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
section "2. Gateway Configuration"
|
||||
# =============================================================================
|
||||
|
||||
if [[ -f "$CONFIG_FILE" ]]; then
|
||||
|
||||
# Check bind address
|
||||
BIND_ADDR=$(grep -E '^\s*bind:' "$CONFIG_FILE" 2>/dev/null | head -1 | sed 's/.*bind:\s*//' | tr -d '"' | tr -d "'" | xargs)
|
||||
if [[ -z "$BIND_ADDR" ]]; then
|
||||
warn "Gateway bind address not explicitly set (may default to 0.0.0.0)" \
|
||||
"Add to config.yaml under gateway: bind: \"127.0.0.1\""
|
||||
elif [[ "$BIND_ADDR" == "127.0.0.1" || "$BIND_ADDR" == "localhost" ]]; then
|
||||
pass "Gateway binds to loopback only: $BIND_ADDR"
|
||||
elif [[ "$BIND_ADDR" == "0.0.0.0" ]]; then
|
||||
fail "Gateway binds to ALL interfaces (0.0.0.0) — EXPOSED TO NETWORK!" \
|
||||
"CRITICAL: Change gateway.bind to \"127.0.0.1\" in $CONFIG_FILE immediately"
|
||||
else
|
||||
warn "Gateway binds to: $BIND_ADDR — verify this is intentional" \
|
||||
"Recommended: Set gateway.bind to \"127.0.0.1\" unless you have a specific reason"
|
||||
fi
|
||||
|
||||
# Check auth mode
|
||||
AUTH_MODE=$(grep -E '^\s*mode:' "$CONFIG_FILE" 2>/dev/null | head -1 | sed 's/.*mode:\s*//' | tr -d '"' | tr -d "'" | xargs)
|
||||
if [[ "$AUTH_MODE" == "password" ]]; then
|
||||
pass "Gateway auth mode: password"
|
||||
|
||||
# Check password strength
|
||||
PASSWORD=$(grep -E '^\s*password:' "$CONFIG_FILE" 2>/dev/null | head -1 | sed 's/.*password:\s*//' | tr -d '"' | tr -d "'" | xargs)
|
||||
if [[ -z "$PASSWORD" ]]; then
|
||||
fail "Gateway password is EMPTY" \
|
||||
"Set a strong password: openclaw config set gateway.auth.password \"\$(openssl rand -base64 32)\""
|
||||
elif [[ ${#PASSWORD} -lt 16 ]]; then
|
||||
warn "Gateway password is short (${#PASSWORD} chars, recommend 20+)" \
|
||||
"Set stronger password: openclaw config set gateway.auth.password \"\$(openssl rand -base64 32)\""
|
||||
else
|
||||
pass "Gateway password length: ${#PASSWORD} chars"
|
||||
fi
|
||||
elif [[ -z "$AUTH_MODE" ]]; then
|
||||
fail "Gateway auth mode NOT configured — WebChat/Control UI may be unprotected" \
|
||||
"Add to config.yaml: gateway.auth.mode: \"password\" and set a strong password"
|
||||
else
|
||||
warn "Gateway auth mode: $AUTH_MODE — verify this is secure" \
|
||||
"Recommended: Set gateway.auth.mode to \"password\""
|
||||
fi
|
||||
|
||||
# Check DM policy
|
||||
DM_POLICY=$(grep -E '^\s*dmPolicy:' "$CONFIG_FILE" 2>/dev/null | head -1 | sed 's/.*dmPolicy:\s*//' | tr -d '"' | tr -d "'" | xargs)
|
||||
if [[ "$DM_POLICY" == "pairing" ]]; then
|
||||
pass "DM policy: pairing (unknown senders must be approved)"
|
||||
elif [[ "$DM_POLICY" == "open" ]]; then
|
||||
fail "DM policy is OPEN — ANYONE can message your bot!" \
|
||||
"CRITICAL: Change dmPolicy to \"pairing\" in $CONFIG_FILE immediately"
|
||||
elif [[ -z "$DM_POLICY" ]]; then
|
||||
warn "DM policy not explicitly set (check default behavior)" \
|
||||
"Explicitly set dmPolicy: \"pairing\" in $CONFIG_FILE"
|
||||
else
|
||||
info "DM policy: $DM_POLICY"
|
||||
fi
|
||||
|
||||
# Check Tailscale mode
|
||||
TS_MODE=$(grep -A5 "tailscale:" "$CONFIG_FILE" 2>/dev/null | grep -E '^\s*mode:' | head -1 | sed 's/.*mode:\s*//' | tr -d '"' | tr -d "'" | xargs)
|
||||
if [[ "$TS_MODE" == "serve" ]]; then
|
||||
pass "Tailscale mode: serve (tailnet-only, not public)"
|
||||
elif [[ "$TS_MODE" == "funnel" ]]; then
|
||||
fail "Tailscale mode is FUNNEL — Gateway is publicly accessible!" \
|
||||
"Change tailscale.mode to \"serve\" unless you absolutely need public access. If you do, ensure gateway.auth.mode is \"password\" with a strong password."
|
||||
elif [[ -z "$TS_MODE" || "$TS_MODE" == "off" ]]; then
|
||||
pass "Tailscale mode: off/unset (no Tailscale exposure)"
|
||||
fi
|
||||
|
||||
# Check for dangerous tools
|
||||
SYSTEM_RUN=$(grep -A3 "system:" "$CONFIG_FILE" 2>/dev/null | grep -A1 "run:" | grep "enabled:" | sed 's/.*enabled:\s*//' | tr -d ' ' | head -1)
|
||||
if [[ "$SYSTEM_RUN" == "true" ]]; then
|
||||
fail "system.run tool is ENABLED — allows arbitrary command execution!" \
|
||||
"CRITICAL: Disable system.run in config.yaml: tools.system.run.enabled: false"
|
||||
elif [[ "$SYSTEM_RUN" == "false" ]]; then
|
||||
pass "system.run tool: disabled"
|
||||
else
|
||||
warn "system.run tool status unknown — verify manually" \
|
||||
"Explicitly set tools.system.run.enabled: false in $CONFIG_FILE"
|
||||
fi
|
||||
|
||||
BROWSER_ENABLED=$(grep -A2 "browser:" "$CONFIG_FILE" 2>/dev/null | grep "enabled:" | sed 's/.*enabled:\s*//' | tr -d ' ' | head -1)
|
||||
if [[ "$BROWSER_ENABLED" == "true" ]]; then
|
||||
warn "Browser control is ENABLED — agent can browse authenticated sessions" \
|
||||
"Disable browser unless needed: tools.browser.enabled: false"
|
||||
elif [[ "$BROWSER_ENABLED" == "false" ]]; then
|
||||
pass "Browser control: disabled"
|
||||
else
|
||||
warn "Browser control status unknown — verify manually" \
|
||||
"Explicitly set tools.browser.enabled: false in $CONFIG_FILE"
|
||||
fi
|
||||
|
||||
else
|
||||
info "Skipping config checks — config file not found"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
section "3. File Permissions"
|
||||
# =============================================================================
|
||||
|
||||
if [[ -d "$OPENCLAW_DIR" ]]; then
|
||||
# Check ~/.openclaw directory permissions
|
||||
DIR_PERMS=$(stat -c "%a" "$OPENCLAW_DIR" 2>/dev/null || stat -f "%Lp" "$OPENCLAW_DIR" 2>/dev/null)
|
||||
if [[ "$DIR_PERMS" == "700" ]]; then
|
||||
pass "~/.openclaw/ directory permissions: $DIR_PERMS (owner-only)"
|
||||
else
|
||||
fail "~/.openclaw/ directory permissions: $DIR_PERMS (should be 700)" \
|
||||
"Fix: chmod 700 ~/.openclaw"
|
||||
fi
|
||||
|
||||
# Check config file permissions
|
||||
if [[ -f "$CONFIG_FILE" ]]; then
|
||||
FILE_PERMS=$(stat -c "%a" "$CONFIG_FILE" 2>/dev/null || stat -f "%Lp" "$CONFIG_FILE" 2>/dev/null)
|
||||
if [[ "$FILE_PERMS" == "600" ]]; then
|
||||
pass "config.yaml permissions: $FILE_PERMS (owner read/write only)"
|
||||
else
|
||||
fail "config.yaml permissions: $FILE_PERMS (should be 600 — contains API keys!)" \
|
||||
"Fix: chmod 600 ~/.openclaw/config.yaml"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check WhatsApp session directory
|
||||
WA_DIR="$OPENCLAW_DIR/whatsapp"
|
||||
if [[ -d "$WA_DIR" ]]; then
|
||||
WA_PERMS=$(stat -c "%a" "$WA_DIR" 2>/dev/null || stat -f "%Lp" "$WA_DIR" 2>/dev/null)
|
||||
if [[ "$WA_PERMS" == "700" ]]; then
|
||||
pass "WhatsApp session dir permissions: $WA_PERMS"
|
||||
else
|
||||
warn "WhatsApp session dir permissions: $WA_PERMS (should be 700)" \
|
||||
"Fix: chmod -R 700 ~/.openclaw/whatsapp"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
info "~/.openclaw/ directory not found — skipping permission checks"
|
||||
fi
|
||||
|
||||
# Check running as root
|
||||
if [[ "$(id -u)" == "0" ]]; then
|
||||
fail "Running as ROOT — never run OpenClaw as root!" \
|
||||
"Switch to a regular user: su - yourusername"
|
||||
else
|
||||
pass "Not running as root: $(whoami)"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
section "4. Network Security"
|
||||
# =============================================================================
|
||||
|
||||
# Check if Gateway port is listening
|
||||
GW_PORT=18789
|
||||
if [[ -f "$CONFIG_FILE" ]]; then
|
||||
CUSTOM_PORT=$(grep -E '^\s*port:' "$CONFIG_FILE" 2>/dev/null | head -1 | sed 's/.*port:\s*//' | tr -d ' ')
|
||||
if [[ -n "$CUSTOM_PORT" && "$CUSTOM_PORT" =~ ^[0-9]+$ ]]; then
|
||||
GW_PORT=$CUSTOM_PORT
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v ss &>/dev/null; then
|
||||
LISTEN_ADDR=$(ss -tlnp 2>/dev/null | grep ":${GW_PORT}" | awk '{print $4}' | head -1)
|
||||
elif command -v lsof &>/dev/null; then
|
||||
LISTEN_ADDR=$(lsof -iTCP:${GW_PORT} -sTCP:LISTEN -P -n 2>/dev/null | awk 'NR>1{print $9}' | head -1)
|
||||
else
|
||||
LISTEN_ADDR=""
|
||||
fi
|
||||
|
||||
if [[ -n "$LISTEN_ADDR" ]]; then
|
||||
if echo "$LISTEN_ADDR" | grep -q "127.0.0.1\|localhost\|\[::1\]"; then
|
||||
pass "Gateway listening on loopback only: $LISTEN_ADDR"
|
||||
elif echo "$LISTEN_ADDR" | grep -q "0.0.0.0\|\*:\|\[::\]"; then
|
||||
fail "Gateway listening on ALL interfaces: $LISTEN_ADDR" \
|
||||
"CRITICAL: Change gateway.bind to \"127.0.0.1\" and restart OpenClaw"
|
||||
else
|
||||
warn "Gateway listening on: $LISTEN_ADDR — verify this is intentional" \
|
||||
"Recommended: Bind to 127.0.0.1 unless you have a specific reason"
|
||||
fi
|
||||
else
|
||||
info "Gateway not currently running on port $GW_PORT (or cannot detect)"
|
||||
fi
|
||||
|
||||
# Check SSH
|
||||
if [[ "$OS" == "wsl2" || "$OS" == "linux" ]]; then
|
||||
if systemctl is-active ssh &>/dev/null 2>&1 || systemctl is-active sshd &>/dev/null 2>&1; then
|
||||
warn "SSH service is RUNNING — disable if not needed" \
|
||||
"Disable SSH: sudo systemctl disable --now ssh"
|
||||
else
|
||||
pass "SSH service: not running"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check UFW (Linux/WSL2)
|
||||
if [[ "$OS" == "wsl2" || "$OS" == "linux" ]]; then
|
||||
if command -v ufw &>/dev/null; then
|
||||
UFW_STATUS=$(sudo ufw status 2>/dev/null | head -1 || echo "unknown")
|
||||
if echo "$UFW_STATUS" | grep -q "active"; then
|
||||
pass "UFW firewall: active"
|
||||
else
|
||||
warn "UFW firewall: inactive" \
|
||||
"Enable: sudo ufw default deny incoming && sudo ufw allow from 127.0.0.1 to any port $GW_PORT && sudo ufw enable"
|
||||
fi
|
||||
else
|
||||
warn "UFW not installed" \
|
||||
"Install: sudo apt install -y ufw && sudo ufw default deny incoming && sudo ufw enable"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check macOS firewall
|
||||
if [[ "$OS" == "macos" ]]; then
|
||||
FW_STATE=$(sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate 2>/dev/null | grep -o "enabled\|disabled" || echo "unknown")
|
||||
if [[ "$FW_STATE" == "enabled" ]]; then
|
||||
pass "macOS firewall: enabled"
|
||||
elif [[ "$FW_STATE" == "disabled" ]]; then
|
||||
warn "macOS firewall: disabled" \
|
||||
"Enable: System Settings → Network → Firewall → Turn On"
|
||||
else
|
||||
info "Could not check macOS firewall state"
|
||||
fi
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
section "5. API Key Security"
|
||||
# =============================================================================
|
||||
|
||||
if [[ -f "$CONFIG_FILE" ]]; then
|
||||
# Check for hardcoded API keys
|
||||
if grep -qE 'sk-[a-zA-Z0-9]{20,}' "$CONFIG_FILE" 2>/dev/null; then
|
||||
warn "Hardcoded OpenAI API key found in config.yaml" \
|
||||
"Prefer OAuth login: openclaw auth login openai (keys in config are readable by anyone with file access)"
|
||||
else
|
||||
pass "No hardcoded OpenAI API key in config.yaml"
|
||||
fi
|
||||
|
||||
if grep -qE 'sk-ant-[a-zA-Z0-9]{20,}' "$CONFIG_FILE" 2>/dev/null; then
|
||||
warn "Hardcoded Anthropic API key found in config.yaml" \
|
||||
"Prefer OAuth login: openclaw auth login anthropic"
|
||||
else
|
||||
pass "No hardcoded Anthropic API key in config.yaml"
|
||||
fi
|
||||
|
||||
# Check if config is in a git repo
|
||||
if git -C "$OPENCLAW_DIR" rev-parse --is-inside-work-tree &>/dev/null; then
|
||||
fail "~/.openclaw/ is inside a git repo — API keys may be committed!" \
|
||||
"Add .openclaw/ to .gitignore immediately: echo '.openclaw/' >> ~/.gitignore_global"
|
||||
else
|
||||
pass "~/.openclaw/ is NOT inside a git repo"
|
||||
fi
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
section "6. System Security"
|
||||
# =============================================================================
|
||||
|
||||
# Check OS updates
|
||||
if [[ "$OS" == "wsl2" || "$OS" == "linux" ]]; then
|
||||
UPGRADABLE=$(apt list --upgradable 2>/dev/null | grep -c "upgradable" || echo "0")
|
||||
if [[ "$UPGRADABLE" -gt 10 ]]; then
|
||||
warn "$UPGRADABLE packages have available updates" \
|
||||
"Update: sudo apt update && sudo apt upgrade -y"
|
||||
elif [[ "$UPGRADABLE" -gt 0 ]]; then
|
||||
info "$UPGRADABLE packages have available updates"
|
||||
else
|
||||
pass "System packages: up to date"
|
||||
fi
|
||||
elif [[ "$OS" == "macos" ]]; then
|
||||
BREW_OUTDATED=$(brew outdated 2>/dev/null | wc -l | tr -d ' ')
|
||||
if [[ "$BREW_OUTDATED" -gt 10 ]]; then
|
||||
warn "$BREW_OUTDATED Homebrew packages are outdated" \
|
||||
"Update: brew update && brew upgrade"
|
||||
else
|
||||
pass "Homebrew packages: mostly up to date ($BREW_OUTDATED outdated)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check WSL2 systemd
|
||||
if [[ "$OS" == "wsl2" ]]; then
|
||||
if [[ -f /etc/wsl.conf ]] && grep -q "systemd=true" /etc/wsl.conf 2>/dev/null; then
|
||||
pass "WSL2 systemd: enabled (daemon auto-start works)"
|
||||
else
|
||||
warn "WSL2 systemd not enabled — OpenClaw daemon won't auto-start" \
|
||||
"Add [boot] systemd=true to /etc/wsl.conf and restart WSL (wsl --shutdown)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for open ports
|
||||
if command -v ss &>/dev/null; then
|
||||
OPEN_PORTS=$(ss -tlnp 2>/dev/null | grep -c "0.0.0.0\|\[::\]" || echo "0")
|
||||
if [[ "$OPEN_PORTS" -gt 5 ]]; then
|
||||
warn "$OPEN_PORTS services listening on all interfaces" \
|
||||
"Review open ports: ss -tlnp | grep '0.0.0.0' — close anything you don't need"
|
||||
else
|
||||
pass "Open ports on all interfaces: $OPEN_PORTS (reasonable)"
|
||||
fi
|
||||
elif command -v lsof &>/dev/null; then
|
||||
OPEN_PORTS=$(lsof -iTCP -sTCP:LISTEN -P -n 2>/dev/null | grep -c "\*:" || echo "0")
|
||||
if [[ "$OPEN_PORTS" -gt 5 ]]; then
|
||||
warn "$OPEN_PORTS services listening on all interfaces" \
|
||||
"Review open ports: lsof -iTCP -sTCP:LISTEN -P -n | grep '\\*:' — close anything you don't need"
|
||||
else
|
||||
pass "Open ports on all interfaces: $OPEN_PORTS (reasonable)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
section "7. OpenClaw Doctor"
|
||||
# =============================================================================
|
||||
|
||||
if command -v openclaw &>/dev/null; then
|
||||
info "Running 'openclaw doctor' for built-in health check..."
|
||||
echo ""
|
||||
openclaw doctor 2>&1 | sed 's/^/ /' || warn "openclaw doctor failed" "Run manually: openclaw doctor"
|
||||
echo ""
|
||||
else
|
||||
info "Skipping — OpenClaw not installed"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# SUMMARY
|
||||
# =============================================================================
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${BOLD} SECURITY SCAN SUMMARY${NC}"
|
||||
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
|
||||
TOTAL=$((PASS + FAIL + WARN))
|
||||
echo -e " ${GREEN}✅ Passed: $PASS${NC}"
|
||||
echo -e " ${RED}❌ Failed: $FAIL${NC}"
|
||||
echo -e " ${YELLOW}⚠️ Warnings: $WARN${NC}"
|
||||
echo -e " ─────────────────"
|
||||
echo -e " ${BOLD}Total checks: $TOTAL${NC}"
|
||||
echo ""
|
||||
|
||||
if [[ $FAIL -eq 0 && $WARN -eq 0 ]]; then
|
||||
echo -e " ${GREEN}${BOLD}🎉 ALL CLEAR — Your OpenClaw setup is secure!${NC}"
|
||||
elif [[ $FAIL -eq 0 ]]; then
|
||||
echo -e " ${YELLOW}${BOLD}⚠️ MOSTLY SECURE — Review warnings below${NC}"
|
||||
elif [[ $FAIL -le 2 ]]; then
|
||||
echo -e " ${RED}${BOLD}🔴 ACTION REQUIRED — Fix the issues below before going live${NC}"
|
||||
else
|
||||
echo -e " ${RED}${BOLD}🚨 CRITICAL — Multiple security issues detected!${NC}"
|
||||
fi
|
||||
|
||||
# Print recommendations
|
||||
if [[ ${#RECOMMENDATIONS[@]} -gt 0 ]]; then
|
||||
echo ""
|
||||
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${BOLD} RECOMMENDATIONS (fix in order)${NC}"
|
||||
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
|
||||
REC_NUM=1
|
||||
for rec in "${RECOMMENDATIONS[@]}"; do
|
||||
echo -e " ${BOLD}${REC_NUM}.${NC} $rec"
|
||||
echo ""
|
||||
((REC_NUM++))
|
||||
done
|
||||
fi
|
||||
|
||||
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e " Run this script again after fixing issues: ${BOLD}bash validate-security.sh${NC}"
|
||||
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
|
||||
# Exit with non-zero if any failures
|
||||
if [[ $FAIL -gt 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
Loading…
Reference in New Issue
Block a user