Files
microdao-daarion/scripts/rebuild-daarion-web-secure.sh
Apple d77a4769c6 🔒 security(daarion-web): Hardening after crypto-mining incidents
## Root Cause Analysis
- Found CRITICAL RCE vulnerability in Next.js 15.0.3 (GHSA-9qr9-h5gf-34mp)
- 10 vulnerabilities total including SSRF, DoS, Auth Bypass
- Attack vector: exposed port 3000 + vulnerable Next.js → remote code execution

## Security Fixes
- Upgraded Next.js: 15.0.3 → 15.5.9 (0 vulnerabilities)
- Upgraded eslint-config-next: 15.0.3 → 15.5.9

## Hardening (New Files)
- apps/web/Dockerfile.secure: Multi-stage build, read-only FS, no shell
- docker-compose.web.secure.yml: Resource limits, cap_drop ALL, localhost bind
- scripts/rebuild-daarion-web-secure.sh: Local secure rebuild with Trivy scan
- scripts/deploy-daarion-web-node1.sh: Production deployment to NODE1
- SECURITY-REBUILD-REPORT.md: Full incident analysis and remediation report

## Key Security Measures
- restart: "no" (until verified)
- ports: 127.0.0.1:3000 (localhost only, use Nginx reverse proxy)
- read_only: true
- cap_drop: ALL
- resources.limits: 1 CPU, 512M RAM
- no-new-privileges: true

## Related Incidents
- Incident #1 (Jan 8): catcal, G4NQXBp miners
- Incident #2 (Jan 9): softirq, vrarhpb miners
- Hetzner AbuseID: 10F3971:2A

Co-authored-by: Cursor Agent <agent@cursor.sh>
2026-01-09 02:08:13 -08:00

202 lines
6.2 KiB
Bash
Executable File

#!/bin/bash
# ============================================
# DAARION Web - Secure Rebuild Script
# Version: 1.0.0
# Created: 2026-01-09
# Purpose: Rebuild daarion-web with security hardening
# ============================================
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
PROJECT_DIR="/Users/apple/github-projects/microdao-daarion"
WEB_DIR="${PROJECT_DIR}/apps/web"
IMAGE_NAME="daarion-web"
IMAGE_TAG="secure-$(date +%Y%m%d-%H%M%S)"
COMPOSE_FILE="${PROJECT_DIR}/docker-compose.web.secure.yml"
echo -e "${BLUE}============================================${NC}"
echo -e "${BLUE} DAARION Web - Secure Rebuild Script${NC}"
echo -e "${BLUE}============================================${NC}"
echo ""
# ============================================
# Step 1: Pre-flight checks
# ============================================
echo -e "${YELLOW}[1/7] Pre-flight checks...${NC}"
# Check Docker
if ! command -v docker &> /dev/null; then
echo -e "${RED}ERROR: Docker is not installed${NC}"
exit 1
fi
# Check Trivy
if ! command -v trivy &> /dev/null; then
echo -e "${YELLOW}WARNING: Trivy not found. Installing...${NC}"
brew install trivy 2>/dev/null || {
echo -e "${YELLOW}Installing Trivy via script...${NC}"
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
}
fi
echo -e "${GREEN}✓ Pre-flight checks passed${NC}"
# ============================================
# Step 2: Clean old images and containers
# ============================================
echo -e "${YELLOW}[2/7] Cleaning old images and containers...${NC}"
# Stop and remove existing container
docker stop ${IMAGE_NAME} 2>/dev/null || true
docker rm ${IMAGE_NAME} 2>/dev/null || true
# Remove old images (keep none to prevent cache poisoning)
docker images | grep ${IMAGE_NAME} | awk '{print $3}' | xargs -r docker rmi -f 2>/dev/null || true
# Clear build cache
docker builder prune -f 2>/dev/null || true
echo -e "${GREEN}✓ Cleanup completed${NC}"
# ============================================
# Step 3: Audit npm dependencies
# ============================================
echo -e "${YELLOW}[3/7] Auditing npm dependencies...${NC}"
cd "${WEB_DIR}"
# Run npm audit
echo "Running npm audit..."
npm audit --audit-level=high 2>&1 || {
echo -e "${YELLOW}WARNING: npm audit found issues. Review above.${NC}"
read -p "Continue anyway? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo -e "${RED}Aborted by user${NC}"
exit 1
fi
}
echo -e "${GREEN}✓ npm audit completed${NC}"
# ============================================
# Step 4: Build secure image
# ============================================
echo -e "${YELLOW}[4/7] Building secure Docker image...${NC}"
cd "${PROJECT_DIR}"
# Build with no-cache to prevent layer poisoning
docker build \
--no-cache \
--pull \
-t ${IMAGE_NAME}:${IMAGE_TAG} \
-t ${IMAGE_NAME}:latest \
-f "${WEB_DIR}/Dockerfile.secure" \
"${WEB_DIR}"
echo -e "${GREEN}✓ Image built: ${IMAGE_NAME}:${IMAGE_TAG}${NC}"
# ============================================
# Step 5: Security scanning with Trivy
# ============================================
echo -e "${YELLOW}[5/7] Running Trivy security scan...${NC}"
echo "Scanning for vulnerabilities..."
trivy image --severity HIGH,CRITICAL ${IMAGE_NAME}:${IMAGE_TAG}
SCAN_EXIT=$?
if [ $SCAN_EXIT -ne 0 ]; then
echo -e "${RED}WARNING: Trivy found HIGH/CRITICAL vulnerabilities!${NC}"
read -p "Continue deployment? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo -e "${RED}Aborted by user${NC}"
exit 1
fi
fi
# Full scan report
echo "Generating full scan report..."
trivy image --format json -o "${PROJECT_DIR}/logs/trivy-scan-${IMAGE_TAG}.json" ${IMAGE_NAME}:${IMAGE_TAG}
echo -e "${GREEN}✓ Security scan completed${NC}"
echo -e " Report: ${PROJECT_DIR}/logs/trivy-scan-${IMAGE_TAG}.json"
# ============================================
# Step 6: Test container locally
# ============================================
echo -e "${YELLOW}[6/7] Testing container locally...${NC}"
# Start container
docker compose -f "${COMPOSE_FILE}" up -d
echo "Waiting for container to start..."
sleep 10
# Check container is running
if ! docker ps | grep -q ${IMAGE_NAME}; then
echo -e "${RED}ERROR: Container failed to start${NC}"
docker logs ${IMAGE_NAME}
exit 1
fi
# Check health
echo "Checking container health..."
for i in {1..5}; do
HEALTH=$(docker inspect --format='{{.State.Health.Status}}' ${IMAGE_NAME} 2>/dev/null || echo "unknown")
echo " Health status: $HEALTH"
if [ "$HEALTH" == "healthy" ]; then
break
fi
sleep 5
done
# Check for suspicious processes
echo "Checking for suspicious processes..."
docker exec ${IMAGE_NAME} ps aux 2>/dev/null || echo "(ps not available - expected in hardened container)"
# Check CPU usage (should be low)
echo "Monitoring CPU usage for 30 seconds..."
for i in {1..6}; do
docker stats --no-stream --format "{{.Name}}: CPU {{.CPUPerc}}, MEM {{.MemUsage}}" ${IMAGE_NAME}
sleep 5
done
echo -e "${GREEN}✓ Container test passed${NC}"
# ============================================
# Step 7: Summary
# ============================================
echo ""
echo -e "${BLUE}============================================${NC}"
echo -e "${GREEN} BUILD COMPLETED SUCCESSFULLY${NC}"
echo -e "${BLUE}============================================${NC}"
echo ""
echo -e "Image: ${IMAGE_NAME}:${IMAGE_TAG}"
echo -e "Container: ${IMAGE_NAME}"
echo -e "Status: Running"
echo ""
echo -e "${YELLOW}NEXT STEPS:${NC}"
echo "1. Monitor container for 15+ minutes:"
echo " docker logs -f ${IMAGE_NAME}"
echo " docker stats ${IMAGE_NAME}"
echo ""
echo "2. If stable, deploy to production:"
echo " - Copy image to NODE1: docker save ${IMAGE_NAME}:${IMAGE_TAG} | ssh root@144.76.224.179 docker load"
echo " - Or rebuild on NODE1 using Dockerfile.secure"
echo ""
echo "3. Enable auto-restart after verification:"
echo " - Edit docker-compose.web.secure.yml"
echo " - Change restart: \"no\" to restart: \"unless-stopped\""
echo ""
echo -e "${RED}⚠️ DO NOT deploy to production without 15+ min monitoring!${NC}"