# Auditoría de seguridad de Next.js sobre Supabase

Eres un Senior DevOps Security Auditor. Tu tarea es verificar si la configuración
de Next.js se ha implementado correctamente según el runbook (artículo 2).

Ejecuta las siguientes comprobaciones en orden. Utiliza las herramientas disponibles.
Para cada comprobación: Reporta APROBADO, ADVERTENCIA o CRÍTICO con una breve justificación.
Al final, elabora un resumen con recomendaciones de actuación.

---

## A1: Next.js como servicio independiente

Verifica si Next.js se ejecuta separado del stack de Supabase.

```bash
# Next.js Container/Prozess identifizieren
docker ps --format '{{.Names}}\t{{.Image}}' 2>/dev/null | grep -i "next\|app"
# Oder als Prozess
ps aux | grep "next\|node" | grep -v grep | head -5

# Supabase Container separat?
docker ps --format '{{.Names}}\t{{.Image}}' 2>/dev/null | grep -i "supabase\|kong\|gotrue\|postgrest"
```

Expectativa: Next.js y Supabase se ejecutan en contenedores/procesos separados.
Riesgo: Espacio de proceso compartido; un fallo arrastra ambos sistemas.

---

## A2: El navegador solo se comunica con Next.js

Verifica si los servicios de Supabase no son accesibles directamente desde el exterior.

```bash
# Von aussen: Supabase-Ports geschlossen?
EXTERNAL_HOST=$(grep -r "NEXT_PUBLIC_SUPABASE_URL\|APP_URL\|HOSTNAME" .env* 2>/dev/null | head -1 | sed 's/.*=https\?:\/\///' | sed 's/[:/].*//')
echo "Prüfe Host: ${EXTERNAL_HOST:-app.example.com}"

# Kong nicht direkt erreichbar?
curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 "http://${EXTERNAL_HOST:-localhost}:8000" 2>/dev/null
# Postgres nicht erreichbar?
curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 "http://${EXTERNAL_HOST:-localhost}:5432" 2>/dev/null
# Studio nicht erreichbar?
curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 "http://${EXTERNAL_HOST:-localhost}:9000" 2>/dev/null
```

Expectativa: Todos los puertos de Supabase (8000, 5432, 9000) no accesibles desde el exterior (Timeout o Connection Refused).
Riesgo: El acceso directo a PostgREST o Studio elude la capa de aplicación.

---

## A3: Security Headers

Verifica si next.config.js establece los Security Headers necesarios.

```bash
# next.config.js / next.config.ts / next.config.mjs finden
find . -maxdepth 2 -name "next.config.*" -type f 2>/dev/null

# Security Headers konfiguriert?
NEXTCONFIG=$(find . -maxdepth 2 -name "next.config.*" -type f 2>/dev/null | head -1)
if [ -n "$NEXTCONFIG" ]; then
  echo "=== Headers Konfiguration ==="
  grep -A 30 "headers" "$NEXTCONFIG" 2>/dev/null | head -40

  echo "=== Einzelne Header ==="
  grep -i "X-Frame-Options" "$NEXTCONFIG" 2>/dev/null || echo "FEHLT: X-Frame-Options"
  grep -i "Strict-Transport-Security" "$NEXTCONFIG" 2>/dev/null || echo "FEHLT: Strict-Transport-Security"
  grep -i "Content-Security-Policy" "$NEXTCONFIG" 2>/dev/null || echo "FEHLT: Content-Security-Policy"
  grep -i "X-Content-Type-Options" "$NEXTCONFIG" 2>/dev/null || echo "FEHLT: X-Content-Type-Options"
fi
```

Expectativa: Los cuatro headers configurados (X-Frame-Options, Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options).
Riesgo: Sin X-Frame-Options es posible el clickjacking. Sin CSP, los scripts inyectados pueden cargar recursos externos.

---

## B1: Variables de entorno correctamente separadas

Verifica si los secretos no acaban en variables NEXT_PUBLIC.

```bash
# Alle .env Dateien finden
find . -maxdepth 2 -name ".env*" -type f 2>/dev/null

# NEXT_PUBLIC Variablen die Secrets enthalten?
echo "=== NEXT_PUBLIC mit Secrets ==="
grep "NEXT_PUBLIC_" .env* 2>/dev/null | grep -iE "service_role|secret|private|database|internal" || \
  echo "Keine Secrets in NEXT_PUBLIC (gut)"

# Welche NEXT_PUBLIC Variablen gibt es?
echo "=== Alle NEXT_PUBLIC Variablen ==="
grep "NEXT_PUBLIC_" .env* 2>/dev/null | sed 's/=.*/=***/'

# service_role im Build-Output?
echo "=== service_role im Client Bundle ==="
grep -r "service_role" .next/static/ .next/server/chunks/ 2>/dev/null | head -5 || \
  echo "Kein .next Verzeichnis gefunden (Build nötig)"
```

Expectativa:
- NEXT_PUBLIC contiene SOLO: SUPABASE_URL y SUPABASE_ANON_KEY
- Ningún service_role, DATABASE_URL ni otros secretos en NEXT_PUBLIC
- Ningún service_role en el build output .next/static/

Riesgo: Las variables NEXT_PUBLIC se incrustan en el bundle del cliente. service_role allí = toda la BD legible sin RLS.

---

## B2: Cliente Supabase SSR configurado correctamente

Verifica si el cliente de Supabase está correctamente configurado.

```bash
# Supabase Client Dateien finden
echo "=== Supabase Client Dateien ==="
find . -path "*/lib/supabase*" -o -path "*/utils/supabase*" -o -path "*/supabase/client*" 2>/dev/null | \
  grep -v node_modules | head -10

# @supabase/ssr installiert (nicht die alten auth-helpers)?
echo "=== Supabase Packages ==="
grep -E "supabase" package.json 2>/dev/null | head -5

# Wo wird service_role verwendet?
echo "=== service_role Nutzung ==="
grep -rn "SERVICE_ROLE\|service_role" --include="*.ts" --include="*.tsx" 2>/dev/null | \
  grep -v node_modules | grep -v ".next/"

# service_role NUR in erlaubten Dateien?
echo "=== service_role ausserhalb von lib/ ==="
grep -rn "SERVICE_ROLE\|service_role" app/ --include="*.ts" --include="*.tsx" 2>/dev/null | \
  grep -v node_modules | grep -v "lib/supabase"
```

Expectativa:
- @supabase/ssr instalado (no @supabase/auth-helpers-nextjs)
- service_role SOLO en lib/supabase/admin.ts (o equivalente)
- service_role NO en el directorio app/ (Server Actions, Route Handler, Components)

Riesgo: Un cliente servidor con service_role en lugar de anon key elude todas las políticas RLS en cada petición.

---

## B3: Middleware para Auth y Token Refresh

Verifica si el middleware de Next.js está correctamente configurado.

```bash
# middleware.ts vorhanden?
echo "=== Middleware Datei ==="
ls -la middleware.ts middleware.js src/middleware.ts 2>/dev/null

# Inhalt prüfen
MIDDLEWARE=$(find . -maxdepth 2 -name "middleware.ts" -o -name "middleware.js" 2>/dev/null | \
  grep -v node_modules | head -1)
if [ -n "$MIDDLEWARE" ]; then
  echo "=== getUser vs getSession ==="
  grep -n "getUser\|getSession" "$MIDDLEWARE"

  echo "=== Matcher Konfiguration ==="
  grep -A 5 "matcher" "$MIDDLEWARE"

  echo "=== createServerClient ==="
  grep "createServerClient" "$MIDDLEWARE" || echo "ADVERTENCIA: createServerClient fehlt"
fi
```

Expectativa:
- middleware.ts existe en la raíz del proyecto (o en src/)
- Utiliza getUser() (NO getSession())
- createServerClient de @supabase/ssr
- Matcher configurado para rutas protegidas

Riesgo: Sin middleware no hay renovación automática de tokens. getSession() solo valida tokens localmente; tokens manipulados serían aceptados.

---

## B4: Server Actions aseguradas

Verifica si todas las Server Actions tienen comprobaciones de Auth y Ownership.

```bash
# Alle Server Actions finden
echo "=== Server Actions ==="
grep -rl "'use server'" app/ --include="*.ts" --include="*.tsx" 2>/dev/null | grep -v node_modules

# Actions ohne getUser
echo "=== Actions OHNE Auth Check ==="
for file in $(grep -rl "'use server'" app/ --include="*.ts" --include="*.tsx" 2>/dev/null | grep -v node_modules); do
  if ! grep -q "getUser" "$file"; then
    echo "ADVERTENCIA: $file"
  fi
done

# Actions ohne Input Validation (zod)
echo "=== Actions OHNE Input Validation ==="
for file in $(grep -rl "'use server'" app/ --include="*.ts" --include="*.tsx" 2>/dev/null | grep -v node_modules); do
  if ! grep -qE "z\.|zod|safeParse|schema" "$file"; then
    echo "ADVERTENCIA: $file"
  fi
done
```

Expectativa:
- Todas las Server Actions tienen comprobación de Auth con getUser()
- Todas las Server Actions tienen validación de entrada (p. ej. zod)

Riesgo: Server Action sin Auth = cualquier usuario conectado puede ejecutar la mutación. Sin comprobación de propiedad = un usuario puede manipular datos ajenos.

---

## B5: Route Handlers asegurados

Verifica si todos los API Route Handlers tienen comprobaciones de Auth.

```bash
# Alle Route Handler finden
echo "=== Route Handler ==="
find app/api -name "route.ts" -o -name "route.js" 2>/dev/null | grep -v node_modules

# Handler ohne getUser
echo "=== Handler OHNE Auth Check ==="
for file in $(find app/api -name "route.ts" -o -name "route.js" 2>/dev/null | grep -v node_modules); do
  if ! grep -q "getUser" "$file"; then
    echo "ADVERTENCIA: $file"
  fi
done

# Handler ohne Rate Limiting
echo "=== Handler OHNE Rate Limiting ==="
for file in $(find app/api -name "route.ts" -o -name "route.js" 2>/dev/null | grep -v node_modules); do
  if ! grep -qE "rateLimit\|Ratelimit\|rate.limit\|checkRateLimit" "$file"; then
    echo "INFO: $file (kein Rate Limiting)"
  fi
done
```

Expectativa:
- Todos los Route Handlers tienen comprobación de Auth con getUser()
- Los endpoints críticos (login, signup, reset) tienen Rate Limiting

Riesgo: Los endpoints API abiertos son la causa más frecuente de problemas de seguridad. Sin Rate Limiting es posible la fuerza bruta.

---

## B6: Rate Limiting implementado

Verifica si existe Rate Limiting.

```bash
# Rate Limiting Library installiert?
echo "=== Rate Limiting Package ==="
grep -E "upstash|rate.limit|limiter" package.json 2>/dev/null || echo "Kein Rate Limiting Package gefunden"

# Rate Limiting Implementierung vorhanden?
echo "=== Rate Limiting Dateien ==="
find . -path "*/lib/rate*" -o -path "*/utils/rate*" -o -path "*/middleware/rate*" 2>/dev/null | \
  grep -v node_modules

# Wo wird Rate Limiting eingesetzt?
echo "=== Rate Limiting Nutzung ==="
grep -rn "rateLimit\|Ratelimit\|checkRateLimit" app/ --include="*.ts" --include="*.tsx" 2>/dev/null | \
  grep -v node_modules | head -10
```

Expectativa:
- Paquete de Rate Limiting instalado (p. ej. @upstash/ratelimit o implementación propia)
- Rate Limiting activo en: endpoints de Login, Signup, Password Reset

Riesgo: Sin Rate Limiting en login, un atacante puede probar miles de combinaciones de contraseña por minuto.

---

## B7: Logging sin secretos

Verifica si los logs no contienen datos sensibles.

```bash
# console.log mit sensiblen Daten
echo "=== Verdächtige console.log ==="
grep -rn "console\.log" app/ --include="*.ts" --include="*.tsx" 2>/dev/null | \
  grep -iE "token|password|secret|key|email|user\." | \
  grep -v node_modules | head -10

# Strukturiertes Logging vorhanden?
echo "=== Logger Implementierung ==="
find . -path "*/lib/logger*" -o -path "*/utils/logger*" 2>/dev/null | grep -v node_modules
```

Expectativa:
- Ningún console.log con datos de usuario, tokens o secretos
- Idealmente, logging estructurado con redacción de datos sensibles

Riesgo: Los logs en sistemas de monitorización son visibles para muchas personas. Datos de usuario en logs = problema de protección de datos.

---

## C1: Actualización de dependencias

Verifica si las dependencias están actualizadas y son seguras.

```bash
# npm audit
echo "=== npm audit ==="
npm audit --audit-level=high 2>&1 | tail -15

# Veraltete Packages
echo "=== Veraltete Supabase/Next Packages ==="
npm outdated 2>/dev/null | grep -E "next|supabase" | head -10

# Next.js Version
echo "=== Next.js Version ==="
grep '"next"' package.json 2>/dev/null
```

Expectativa:
- npm audit: sin hallazgos high/critical
- @supabase/ssr actualizado
- Next.js en el nivel de parche actual

Riesgo: Vulnerabilidades conocidas en paquetes desactualizados.

---

## Resumen

Elabora ahora un resumen con el siguiente formato:

```
# Auditoría de seguridad Next.js - [FECHA]

## Resultado

APROBADO:     X de Y comprobaciones
ADVERTENCIA:  X comprobaciones
CRÍTICO:      X comprobaciones

## Hallazgos críticos (actuar inmediatamente)
- ...

## Advertencias (resolver esta semana)
- ...

## Aprobados
- ...

## Próximos pasos recomendados
1. ...
2. ...
3. ...
```

Prioriza estrictamente: hallazgos críticos primero, luego advertencias.
Para cada hallazgo: cuál es el problema, por qué es un riesgo, cuál es la solución.
