## 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>
122 lines
3.0 KiB
YAML
122 lines
3.0 KiB
YAML
# DAARION Web Frontend - SECURE Docker Compose
|
|
# Hardened configuration post-security incident
|
|
# Version: 2.0.0
|
|
# Created: 2026-01-09
|
|
|
|
version: '3.8'
|
|
|
|
services:
|
|
web:
|
|
build:
|
|
context: ./apps/web
|
|
dockerfile: Dockerfile.secure
|
|
# Prevent cache from potentially compromised layers
|
|
no_cache: true
|
|
container_name: daarion-web
|
|
|
|
# ⚠️ SECURITY: Changed from "unless-stopped" to "no"
|
|
# Only enable after security verification
|
|
restart: "no"
|
|
|
|
# Port mapping - internal only via reverse proxy
|
|
ports:
|
|
- "127.0.0.1:3000:3000" # Bind to localhost only!
|
|
|
|
environment:
|
|
- NODE_ENV=production
|
|
- INTERNAL_API_URL=http://daarion-city-service:7001
|
|
- CITY_API_BASE_URL=http://daarion-city-service:7001
|
|
- AUTH_API_URL=http://daarion-auth:8080
|
|
- NEXT_PUBLIC_API_BASE_URL=
|
|
- NEXT_PUBLIC_CITY_API_BASE_URL=
|
|
|
|
# ============================================
|
|
# SECURITY HARDENING
|
|
# ============================================
|
|
|
|
# Read-only root filesystem
|
|
read_only: true
|
|
|
|
# Temporary filesystems for Next.js cache
|
|
tmpfs:
|
|
- /tmp:size=64M,mode=1777
|
|
- /app/.next/cache:size=128M,mode=1777
|
|
|
|
# Drop all Linux capabilities
|
|
cap_drop:
|
|
- ALL
|
|
|
|
# Add only necessary capabilities (none needed for Next.js)
|
|
# cap_add:
|
|
# - NET_BIND_SERVICE # Only if binding to port < 1024
|
|
|
|
# Security options
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
|
|
# Resource limits to prevent crypto mining
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1.0'
|
|
memory: 512M
|
|
reservations:
|
|
cpus: '0.25'
|
|
memory: 128M
|
|
|
|
# Disable privileged mode
|
|
privileged: false
|
|
|
|
# User namespace
|
|
user: "1001:1001"
|
|
|
|
# Network configuration
|
|
networks:
|
|
- dagi-network
|
|
|
|
# Health check
|
|
healthcheck:
|
|
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000', (r) => process.exit(r.statusCode < 400 ? 0 : 1))"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 15s
|
|
|
|
# Logging configuration
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# Labels for monitoring
|
|
labels:
|
|
- "security.hardened=true"
|
|
- "security.incident=post-recovery"
|
|
- "security.scan-required=true"
|
|
|
|
networks:
|
|
dagi-network:
|
|
external: true
|
|
|
|
# ============================================
|
|
# DEPLOYMENT NOTES
|
|
# ============================================
|
|
#
|
|
# 1. Build with no-cache:
|
|
# docker compose -f docker-compose.web.secure.yml build --no-cache
|
|
#
|
|
# 2. Scan image before deployment:
|
|
# trivy image daarion-web:latest
|
|
#
|
|
# 3. Test locally first:
|
|
# docker compose -f docker-compose.web.secure.yml up -d
|
|
# docker logs -f daarion-web
|
|
#
|
|
# 4. Monitor for 15+ minutes:
|
|
# docker stats daarion-web
|
|
# docker exec daarion-web ps aux
|
|
#
|
|
# 5. After verification, change restart to "unless-stopped"
|
|
# ============================================
|