# Next.js über Supabase Sicherheits-Audit

Du bist ein Senior DevOps Security Auditor. Deine Aufgabe ist es zu prüfen, ob das
Next.js Setup gemäss dem Runbook (Artikel 2) korrekt umgesetzt wurde.

Führe die folgenden Checks der Reihe nach durch. Nutze dafür die verfügbaren Tools.
Für jeden Check: Melde BESTANDEN, WARNUNG oder KRITISCH mit kurzer Begründung.
Am Ende erstellst du eine Zusammenfassung mit Handlungsempfehlungen.

---

## A1: Next.js als eigener Service

Prüfe ob Next.js getrennt vom Supabase-Stack läuft.

```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"
```

Erwartung: Next.js und Supabase laufen in getrennten Containern/Prozessen.
Risiko: Geteilter Prozessraum, Absturz reisst beide Systeme mit.

---

## A2: Browser spricht nur mit Next.js

Prüfe ob Supabase-Services nicht direkt von aussen erreichbar sind.

```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
```

Erwartung: Alle Supabase-Ports (8000, 5432, 9000) von aussen nicht erreichbar (Timeout oder Connection Refused).
Risiko: Direkter Zugriff auf PostgREST oder Studio umgeht die App-Schicht.

---

## A3: Security Headers

Prüfe ob next.config.js die erforderlichen Security Headers setzt.

```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
```

Erwartung: Alle vier Header konfiguriert (X-Frame-Options, Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options).
Risiko: Ohne X-Frame-Options Clickjacking möglich. Ohne CSP können injizierte Skripte externe Ressourcen laden.

---

## B1: Environment Variables sauber getrennt

Prüfe ob Secrets nicht in NEXT_PUBLIC Variablen landen.

```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)"
```

Erwartung:
- NEXT_PUBLIC enthält NUR: SUPABASE_URL und SUPABASE_ANON_KEY
- Kein service_role, DATABASE_URL oder andere Secrets in NEXT_PUBLIC
- Kein service_role im .next/static/ Build-Output

Risiko: NEXT_PUBLIC Variablen werden ins Client-Bundle eingebettet. service_role dort = gesamte DB ohne RLS lesbar.

---

## B2: Supabase SSR Client korrekt konfiguriert

Prüfe ob der Supabase Client korrekt aufgesetzt ist.

```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"
```

Erwartung:
- @supabase/ssr installiert (nicht @supabase/auth-helpers-nextjs)
- service_role NUR in lib/supabase/admin.ts (oder äquivalent)
- service_role NICHT in app/ Verzeichnis (Server Actions, Route Handler, Components)

Risiko: Server-Client mit service_role statt anon Key umgeht alle RLS-Policies bei jedem Request.

---

## B3: Middleware für Auth und Token Refresh

Prüfe ob die Next.js Middleware korrekt konfiguriert ist.

```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 "WARNUNG: createServerClient fehlt"
fi
```

Erwartung:
- middleware.ts existiert im Projekt-Root (oder src/)
- Verwendet getUser() (NICHT getSession())
- createServerClient aus @supabase/ssr
- Matcher konfiguriert für geschützte Routen

Risiko: Ohne Middleware kein automatischer Token-Refresh. getSession() validiert Tokens nur lokal, manipulierte Tokens werden akzeptiert.

---

## B4: Server Actions abgesichert

Prüfe ob alle Server Actions Auth und Ownership Checks haben.

```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 "WARNUNG: $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 "WARNUNG: $file"
  fi
done
```

Erwartung:
- Alle Server Actions haben getUser() Auth Check
- Alle Server Actions haben Input Validation (z.B. zod)

Risiko: Server Action ohne Auth = jeder eingeloggte User kann die Mutation aufrufen. Ohne Ownership Check = User kann fremde Daten manipulieren.

---

## B5: Route Handler abgesichert

Prüfe ob alle API Route Handler Auth Checks haben.

```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 "WARNUNG: $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
```

Erwartung:
- Alle Route Handler haben getUser() Auth Check
- Kritische Endpoints (login, signup, reset) haben Rate Limiting

Risiko: Offene API-Endpoints sind die häufigste Ursache für Sicherheitsprobleme. Ohne Rate Limiting Brute-Force möglich.

---

## B6: Rate Limiting implementiert

Prüfe ob Rate Limiting vorhanden ist.

```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
```

Erwartung:
- Rate Limiting Package installiert (z.B. @upstash/ratelimit oder eigene Implementierung)
- Rate Limiting aktiv auf: Login, Signup, Password Reset Endpoints

Risiko: Ohne Rate Limiting auf Login kann ein Angreifer tausende Passwort-Kombinationen pro Minute testen.

---

## B7: Logging ohne Secrets

Prüfe ob Logs keine sensiblen Daten enthalten.

```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
```

Erwartung:
- Kein console.log mit User-Daten, Tokens oder Secrets
- Idealerweise strukturiertes Logging mit Redaction

Risiko: Logs in Monitoring-Systemen sind für viele Personen sichtbar. User-Daten in Logs = Datenschutzproblem.

---

## C1: Dependency Updates

Prüfe ob Dependencies aktuell und sicher sind.

```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
```

Erwartung:
- npm audit: keine high/critical Findings
- @supabase/ssr auf aktuellem Stand
- Next.js auf aktuellem Patch-Level

Risiko: Bekannte Vulnerabilities in veralteten Packages.

---

## Zusammenfassung

Erstelle jetzt eine Zusammenfassung in diesem Format:

```
# Next.js Security Audit - [DATUM]

## Ergebnis

BESTANDEN: X von Y Checks
WARNUNG:   X Checks
KRITISCH:  X Checks

## Kritische Findings (sofort handeln)
- ...

## Warnungen (diese Woche lösen)
- ...

## Bestanden
- ...

## Empfohlene nächste Schritte
1. ...
2. ...
3. ...
```

Priorisiere strikt: Kritische Findings zuerst, dann Warnungen.
Für jedes Finding: Was ist das Problem, warum ist es ein Risiko, was ist die Lösung.
