File size: 4,894 Bytes
b6ecafa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#!/usr/bin/env bash
# Mission Control Security Audit
# Run: bash scripts/security-audit.sh [--env-file .env]

set -euo pipefail

SCORE=0
MAX_SCORE=0
ISSUES=()

pass() { echo "  [PASS] $1"; ((SCORE++)); ((MAX_SCORE++)); }
fail() { echo "  [FAIL] $1"; ISSUES+=("$1"); ((MAX_SCORE++)); }
warn() { echo "  [WARN] $1"; ((MAX_SCORE++)); }
info() { echo "  [INFO] $1"; }

# Load .env if exists
ENV_FILE="${1:-.env}"
if [[ -f "$ENV_FILE" ]]; then
  while IFS='=' read -r key value; do
    [[ "$key" =~ ^#.*$ ]] && continue
    [[ -z "$key" ]] && continue
    declare "$key=$value" 2>/dev/null || true
  done < "$ENV_FILE"
fi

echo "=== Mission Control Security Audit ==="
echo ""

# 1. .env file permissions
echo "--- File Permissions ---"
if [[ -f "$ENV_FILE" ]]; then
  perms=$(stat -f '%A' "$ENV_FILE" 2>/dev/null || stat -c '%a' "$ENV_FILE" 2>/dev/null)
  if [[ "$perms" == "600" ]]; then
    pass ".env permissions are 600 (owner read/write only)"
  else
    fail ".env permissions are $perms (should be 600). Run: chmod 600 $ENV_FILE"
  fi
else
  warn ".env file not found at $ENV_FILE"
fi

# 2. Default passwords check
echo ""
echo "--- Credentials ---"
INSECURE_PASSWORDS=("admin" "password" "change-me-on-first-login" "changeme" "testpass123" "testpass1234")
AUTH_PASS_VAL="${AUTH_PASS:-}"
if [[ -z "$AUTH_PASS_VAL" ]]; then
  fail "AUTH_PASS is not set"
else
  insecure=false
  for bad in "${INSECURE_PASSWORDS[@]}"; do
    if [[ "$AUTH_PASS_VAL" == "$bad" ]]; then
      insecure=true; break
    fi
  done
  if $insecure; then
    fail "AUTH_PASS is set to a known insecure default"
  elif [[ ${#AUTH_PASS_VAL} -lt 12 ]]; then
    fail "AUTH_PASS is too short (${#AUTH_PASS_VAL} chars, minimum 12)"
  else
    pass "AUTH_PASS is set to a non-default value (${#AUTH_PASS_VAL} chars)"
  fi
fi

API_KEY_VAL="${API_KEY:-}"
if [[ -z "$API_KEY_VAL" || "$API_KEY_VAL" == "generate-a-random-key" ]]; then
  fail "API_KEY is not set or uses the default value"
else
  pass "API_KEY is configured"
fi

# 3. Network config
echo ""
echo "--- Network Security ---"
MC_ALLOWED="${MC_ALLOWED_HOSTS:-}"
MC_ANY="${MC_ALLOW_ANY_HOST:-}"
if [[ "$MC_ANY" == "1" || "$MC_ANY" == "true" ]]; then
  fail "MC_ALLOW_ANY_HOST is enabled (any host can connect)"
elif [[ -n "$MC_ALLOWED" ]]; then
  pass "MC_ALLOWED_HOSTS is configured: $MC_ALLOWED"
else
  warn "MC_ALLOWED_HOSTS is not set (defaults apply)"
fi

# 4. Cookie/HTTPS config
echo ""
echo "--- HTTPS & Cookies ---"
COOKIE_SECURE="${MC_COOKIE_SECURE:-}"
if [[ "$COOKIE_SECURE" == "1" || "$COOKIE_SECURE" == "true" ]]; then
  pass "MC_COOKIE_SECURE is enabled"
else
  warn "MC_COOKIE_SECURE is not enabled (cookies sent over HTTP)"
fi

SAMESITE="${MC_COOKIE_SAMESITE:-strict}"
if [[ "$SAMESITE" == "strict" ]]; then
  pass "MC_COOKIE_SAMESITE is strict"
else
  warn "MC_COOKIE_SAMESITE is '$SAMESITE' (strict recommended)"
fi

HSTS="${MC_ENABLE_HSTS:-}"
if [[ "$HSTS" == "1" ]]; then
  pass "HSTS is enabled"
else
  warn "HSTS is not enabled (set MC_ENABLE_HSTS=1 for HTTPS deployments)"
fi

# 5. Rate limiting
echo ""
echo "--- Rate Limiting ---"
RL_DISABLED="${MC_DISABLE_RATE_LIMIT:-}"
if [[ "$RL_DISABLED" == "1" ]]; then
  fail "Rate limiting is disabled (MC_DISABLE_RATE_LIMIT=1)"
else
  pass "Rate limiting is active"
fi

# 6. Docker security (if running in Docker)
echo ""
echo "--- Docker Security ---"
if command -v docker &>/dev/null; then
  if docker ps --filter name=mission-control --format '{{.Names}}' 2>/dev/null | grep -q mission-control; then
    ro=$(docker inspect mission-control --format '{{.HostConfig.ReadonlyRootfs}}' 2>/dev/null || echo "false")
    if [[ "$ro" == "true" ]]; then
      pass "Container filesystem is read-only"
    else
      warn "Container filesystem is writable (use read_only: true)"
    fi

    nnp=$(docker inspect mission-control --format '{{.HostConfig.SecurityOpt}}' 2>/dev/null || echo "[]")
    if echo "$nnp" | grep -q "no-new-privileges"; then
      pass "no-new-privileges is set"
    else
      warn "no-new-privileges not set"
    fi

    user=$(docker inspect mission-control --format '{{.Config.User}}' 2>/dev/null || echo "")
    if [[ -n "$user" && "$user" != "root" && "$user" != "0" ]]; then
      pass "Container runs as non-root user ($user)"
    else
      warn "Container may be running as root"
    fi
  else
    info "Mission Control container not running"
  fi
else
  info "Docker not installed (skipping container checks)"
fi

# Summary
echo ""
echo "=== Security Score: $SCORE / $MAX_SCORE ==="
if [[ ${#ISSUES[@]} -gt 0 ]]; then
  echo ""
  echo "Issues to fix:"
  for issue in "${ISSUES[@]}"; do
    echo "  - $issue"
  done
fi

if [[ $SCORE -eq $MAX_SCORE ]]; then
  echo "All checks passed!"
elif [[ $SCORE -ge $((MAX_SCORE * 7 / 10)) ]]; then
  echo "Good security posture with minor improvements needed."
else
  echo "Security improvements recommended before production use."
fi