Security hardening covering credentials, brute-force protection, CSRF, TOCTOU races, upload validation, and migration failure handling. Secret rotation is deferred; the existing secrets in .env will be rotated in a later phase. This phase reduces the attack surface and removes the most exploitable issues. Removed: - Hardcoded 'super'/'admin' super-admin credentials in src/app/api/admin/login/route.ts. Username/hash are now loaded from env (SUPER_ADMIN_USERNAME / SUPER_ADMIN_PASSWORD_HASH) and verified via bcrypt like regular admins. Added: - src/lib/config.ts: single source of truth for APP_DOMAIN, APP_URL, subdomain regex/lengths, validation bounds, admin password policy, image-key allow-list regex, and super-admin env credentials. - src/lib/rate-limit.ts: in-memory LRU (via lru-cache) rate limiters — admin login (5/min), validate-code (20/min), check-subdomain (60/min), upload (10/min) — keyed by client IP, returning 429 with X-RateLimit-* headers. - requireAdmin / requireAdminPost / requireSuperAdminPost guards in src/lib/admin-session.ts. All admin mutating routes now enforce same-origin (Origin/Referer/Host check against NEXT_PUBLIC_APP_URL) before running — CSRF protection for the custom admin auth layer. - Logout now imports COOKIE_NAME_ADMIN instead of hardcoding the string. - Server-side magic-byte detection for image uploads (no new dep) — rejects spoofed Content-Type. GIF removed from allowed types. - /api/publish is now transactional (prisma.) with explicit P2002 → 409 handling for subdomain collisions. - /api/image validates the key against an allow-list regex and returns Macedonian error messages (was the only English-localized file). - /api/validate-code enforces a 12-hex-char pattern and uses updateMany with usedByUserId=null guard to make the claim atomic. - /api/check-subdomain validates the slug against the shared regex before hitting the DB and returns a short private Cache-Control. - Admin password minimum length bumped from 6 to 12 with letter+digit complexity requirement across change-password, users POST and users/[id] PUT. Changed: - scripts/start.sh: prisma migrate deploy failures now exit non-zero instead of silently continuing (prevents schema drift in prod). - .env.example: documents SUPER_ADMIN_USERNAME / SUPER_ADMIN_PASSWORD_HASH with example bcrypt-hash generation. - package.json: lru-cache added as direct dependency (already present transitively, promoted to explicit).
18 lines
433 B
Bash
18 lines
433 B
Bash
#!/bin/sh
|
|
|
|
export HOSTNAME=0.0.0.0
|
|
export PORT=3000
|
|
|
|
echo "=== SpomeniQR Starting ==="
|
|
echo "DATABASE_URL: ${DATABASE_URL:+set}"
|
|
echo "CLERK_SECRET_KEY: ${CLERK_SECRET_KEY:+set}"
|
|
echo "S3_ENDPOINT: ${S3_ENDPOINT:+set}"
|
|
|
|
echo "Running Prisma migrations..."
|
|
if ! npx prisma migrate deploy; then
|
|
echo "ERROR: Prisma migrations failed. Aborting start."
|
|
exit 1
|
|
fi
|
|
|
|
echo "Starting Next.js server on 0.0.0.0:3000..."
|
|
exec node server.js |