Complete snapshot of /opt/microdao-daarion/ from NODE1 (144.76.224.179).
This represents the actual running production code that has diverged
significantly from the previous main branch.
Key changes from old main:
- Gateway (http_api.py): expanded from ~40KB to 164KB with full agent support
- Router: new /v1/agents/{id}/infer endpoint with vision + DeepSeek routing
- Behavior Policy: SOWA v2.2 (3-level: FULL/ACK/SILENT)
- Agent Registry: config/agent_registry.yml as single source of truth
- 13 agents configured (was 3)
- Memory service integration
- CrewAI teams and roles
Excluded from snapshot: venv/, .env, data/, backups, .tgz archives
Co-authored-by: Cursor <cursoragent@cursor.com>
214 lines
6.5 KiB
Bash
Executable File
214 lines
6.5 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# NODE1 Security Regression Test
|
|
# Version: 1.0
|
|
# Last Updated: 2026-01-26
|
|
#
|
|
# Run after each deploy to verify security posture
|
|
#
|
|
# Usage: ./security-regression-test.sh [--remote]
|
|
#
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
# Config
|
|
HOST="${TEST_HOST:-https://gateway.daarion.city}"
|
|
HEALTH_TOKEN="${HEALTH_TOKEN:-dg-health-2026-secret-change-me}"
|
|
|
|
passed=0
|
|
failed=0
|
|
warnings=0
|
|
|
|
# Test helper
|
|
test_check() {
|
|
local name="$1"
|
|
local result="$2"
|
|
local expected="$3"
|
|
|
|
if [ "$result" = "$expected" ]; then
|
|
echo -e "${GREEN}✅ PASS${NC}: $name"
|
|
((passed++))
|
|
else
|
|
echo -e "${RED}❌ FAIL${NC}: $name (got: $result, expected: $expected)"
|
|
((failed++))
|
|
fi
|
|
}
|
|
|
|
test_contains() {
|
|
local name="$1"
|
|
local haystack="$2"
|
|
local needle="$3"
|
|
|
|
if echo "$haystack" | grep -qi "$needle"; then
|
|
echo -e "${GREEN}✅ PASS${NC}: $name"
|
|
((passed++))
|
|
else
|
|
echo -e "${RED}❌ FAIL${NC}: $name (missing: $needle)"
|
|
((failed++))
|
|
fi
|
|
}
|
|
|
|
echo "========================================"
|
|
echo " NODE1 Security Regression Test"
|
|
echo " $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo " Target: $HOST"
|
|
echo "========================================"
|
|
echo ""
|
|
|
|
# === 1. TLS/HSTS ===
|
|
echo "=== 1. TLS & Security Headers ==="
|
|
|
|
headers=$(curl -sS -k -I "$HOST/ping" 2>&1)
|
|
|
|
test_contains "HSTS header present" "$headers" "strict-transport-security"
|
|
test_contains "X-Frame-Options present" "$headers" "x-frame-options"
|
|
test_contains "X-Content-Type-Options present" "$headers" "x-content-type-options"
|
|
test_contains "X-XSS-Protection present" "$headers" "x-xss-protection"
|
|
test_contains "Content-Security-Policy present" "$headers" "content-security-policy"
|
|
|
|
echo ""
|
|
|
|
# === 2. HTTP→HTTPS Redirect ===
|
|
echo "=== 2. HTTP→HTTPS Redirect ==="
|
|
|
|
http_host="${HOST/https:/http:}"
|
|
redirect_code=$(curl -sS -o /dev/null -w "%{http_code}" "$http_host/ping" 2>/dev/null || echo "000")
|
|
test_check "HTTP redirects to HTTPS" "$redirect_code" "301"
|
|
|
|
echo ""
|
|
|
|
# === 3. /health Protection ===
|
|
echo "=== 3. /health Endpoint Protection ==="
|
|
|
|
# Without token (should be 401 or blocked)
|
|
health_no_token=$(curl -sS -k -o /dev/null -w "%{http_code}" "$HOST/health" 2>/dev/null || echo "000")
|
|
if [ "$health_no_token" = "401" ] || [ "$health_no_token" = "403" ]; then
|
|
echo -e "${GREEN}✅ PASS${NC}: /health without token blocked ($health_no_token)"
|
|
((passed++))
|
|
else
|
|
echo -e "${RED}❌ FAIL${NC}: /health without token NOT blocked ($health_no_token)"
|
|
((failed++))
|
|
fi
|
|
|
|
# /ping should work without auth
|
|
ping_code=$(curl -sS -k -o /dev/null -w "%{http_code}" "$HOST/ping" 2>/dev/null || echo "000")
|
|
test_check "/ping accessible without auth" "$ping_code" "200"
|
|
|
|
echo ""
|
|
|
|
# === 4. API Auth Gate ===
|
|
echo "=== 4. API Auth Gate (/v1/*) ==="
|
|
|
|
# Without key (should be 401)
|
|
v1_no_key=$(curl -sS -k -o /dev/null -w "%{http_code}" "$HOST/v1/test" 2>/dev/null || echo "000")
|
|
test_check "/v1/* without API key returns 401" "$v1_no_key" "401"
|
|
|
|
# With invalid key format
|
|
v1_bad_key=$(curl -sS -k -o /dev/null -w "%{http_code}" -H "Authorization: Bearer invalid" "$HOST/v1/test" 2>/dev/null || echo "000")
|
|
test_check "/v1/* with invalid key format returns 401" "$v1_bad_key" "401"
|
|
|
|
echo ""
|
|
|
|
# === 5. WAF Rules ===
|
|
echo "=== 5. WAF Rules ==="
|
|
|
|
# .env should be blocked (444 = connection closed, shows as 000 in curl)
|
|
env_code=$(curl -sS -k -o /dev/null -w "%{http_code}" --max-time 5 "$HOST/.env" 2>&1 | grep -oE '[0-9]{3}$' | tail -1 || echo "000")
|
|
# 000 means connection was closed (444), which is blocked
|
|
if [[ "$env_code" =~ ^0+$ ]] || [ "$env_code" = "444" ] || [ "$env_code" = "403" ]; then
|
|
echo -e "${GREEN}✅ PASS${NC}: /.env blocked (connection closed)"
|
|
((passed++)) || true
|
|
else
|
|
echo -e "${RED}❌ FAIL${NC}: /.env NOT blocked ($env_code)"
|
|
((failed++)) || true
|
|
fi
|
|
|
|
# .git should be blocked
|
|
git_code=$(curl -sS -k -o /dev/null -w "%{http_code}" --max-time 5 "$HOST/.git/config" 2>&1 | grep -oE '[0-9]{3}$' | tail -1 || echo "000")
|
|
if [[ "$git_code" =~ ^0+$ ]] || [ "$git_code" = "444" ] || [ "$git_code" = "403" ]; then
|
|
echo -e "${GREEN}✅ PASS${NC}: /.git blocked (connection closed)"
|
|
((passed++)) || true
|
|
else
|
|
echo -e "${RED}❌ FAIL${NC}: /.git NOT blocked ($git_code)"
|
|
((failed++)) || true
|
|
fi
|
|
|
|
# SQL injection attempt
|
|
sql_code=$(curl -sS -k -o /dev/null -w "%{http_code}" "$HOST/?q=select+*+from+users" 2>/dev/null || echo "000")
|
|
test_check "SQL injection blocked" "$sql_code" "403"
|
|
|
|
# wp-admin blocked
|
|
wp_code=$(curl -sS -k -o /dev/null -w "%{http_code}" --max-time 5 "$HOST/wp-admin/" 2>&1 | grep -oE '[0-9]{3}$' | tail -1 || echo "000")
|
|
if [[ "$wp_code" =~ ^0+$ ]] || [ "$wp_code" = "444" ] || [ "$wp_code" = "403" ]; then
|
|
echo -e "${GREEN}✅ PASS${NC}: /wp-admin blocked (connection closed)"
|
|
((passed++)) || true
|
|
else
|
|
echo -e "${RED}❌ FAIL${NC}: /wp-admin NOT blocked ($wp_code)"
|
|
((failed++)) || true
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# === 6. Rate Limiting ===
|
|
echo "=== 6. Rate Limiting ==="
|
|
|
|
echo -n "Sending 30 rapid requests to /ping... "
|
|
got_429=false
|
|
for i in $(seq 1 30); do
|
|
code=$(curl -sS -k -o /dev/null -w "%{http_code}" "$HOST/ping" 2>/dev/null || echo "000")
|
|
if [ "$code" = "429" ]; then
|
|
got_429=true
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ "$got_429" = true ]; then
|
|
echo -e "${GREEN}✅ PASS${NC}: Rate limit (429) triggered"
|
|
((passed++))
|
|
else
|
|
echo -e "${YELLOW}⚠ WARN${NC}: Rate limit (429) not triggered (may need more requests or higher rate)"
|
|
((warnings++))
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# === 7. Default Route ===
|
|
echo "=== 7. Default Route Security ==="
|
|
|
|
# Unknown endpoint should not expose info
|
|
unknown_code=$(curl -sS -k -o /dev/null -w "%{http_code}" "$HOST/unknown-endpoint-xyz" 2>/dev/null || echo "000")
|
|
if [ "$unknown_code" = "404" ] || [ "$unknown_code" = "401" ] || [ "$unknown_code" = "403" ]; then
|
|
echo -e "${GREEN}✅ PASS${NC}: Unknown endpoint returns safe code ($unknown_code)"
|
|
((passed++))
|
|
else
|
|
echo -e "${YELLOW}⚠ WARN${NC}: Unknown endpoint returns $unknown_code"
|
|
((warnings++))
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# === Summary ===
|
|
echo "========================================"
|
|
echo " Security Regression Test Summary"
|
|
echo "========================================"
|
|
echo ""
|
|
echo -e " ${GREEN}Passed:${NC} $passed"
|
|
echo -e " ${RED}Failed:${NC} $failed"
|
|
echo -e " ${YELLOW}Warnings:${NC} $warnings"
|
|
echo ""
|
|
|
|
if [ "$failed" -gt 0 ]; then
|
|
echo -e "${RED}SECURITY REGRESSION DETECTED${NC}"
|
|
exit 1
|
|
elif [ "$warnings" -gt 0 ]; then
|
|
echo -e "${YELLOW}Tests passed with warnings${NC}"
|
|
exit 0
|
|
else
|
|
echo -e "${GREEN}All security tests passed${NC}"
|
|
exit 0
|
|
fi
|