# Next.js on Supabase Security Audit

You are a Senior DevOps Security Auditor. Your task is to verify whether the
Next.js setup has been correctly implemented according to the runbook (Article 2).

Execute the following checks in order. Use the available tools.
For each check: Report PASS, WARNING, or CRITICAL with a brief justification.
At the end, produce a summary with recommended actions.

---

## A1: Next.js as a Separate Service

Verify that Next.js runs separately from the Supabase stack.

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

Expectation: Next.js and Supabase run in separate containers/processes.
Risk: Shared process space; a crash takes down both systems.

---

## A2: Browser Only Communicates with Next.js

Verify that Supabase services are not directly reachable from outside.

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

Expectation: All Supabase ports (8000, 5432, 9000) not reachable from outside (timeout or connection refused).
Risk: Direct access to PostgREST or Studio bypasses the application layer.

---

## A3: Security Headers

Verify that next.config.js sets the required security headers.

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

Expectation: All four headers configured (X-Frame-Options, Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options).
Risk: Without X-Frame-Options, clickjacking is possible. Without CSP, injected scripts can load external resources.

---

## B1: Environment Variables Properly Separated

Verify that secrets do not leak into NEXT_PUBLIC variables.

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

Expectation:
- NEXT_PUBLIC contains ONLY: SUPABASE_URL and SUPABASE_ANON_KEY
- No service_role, DATABASE_URL, or other secrets in NEXT_PUBLIC
- No service_role in the .next/static/ build output

Risk: NEXT_PUBLIC variables are embedded into the client bundle. service_role there = entire DB readable without RLS.

---

## B2: Supabase SSR Client Correctly Configured

Verify that the Supabase client is properly set up.

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

Expectation:
- @supabase/ssr installed (not @supabase/auth-helpers-nextjs)
- service_role ONLY in lib/supabase/admin.ts (or equivalent)
- service_role NOT in app/ directory (Server Actions, Route Handlers, Components)

Risk: Server client with service_role instead of anon key bypasses all RLS policies on every request.

---

## B3: Middleware for Auth and Token Refresh

Verify that the Next.js middleware is correctly configured.

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

Expectation:
- middleware.ts exists in the project root (or src/)
- Uses getUser() (NOT getSession())
- createServerClient from @supabase/ssr
- Matcher configured for protected routes

Risk: Without middleware, no automatic token refresh. getSession() only validates tokens locally; manipulated tokens are accepted.

---

## B4: Server Actions Secured

Verify that all Server Actions have auth and ownership checks.

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

Expectation:
- All Server Actions have a getUser() auth check
- All Server Actions have input validation (e.g., zod)

Risk: Server Action without auth = any logged-in user can invoke the mutation. Without ownership check = users can manipulate other users' data.

---

## B5: Route Handlers Secured

Verify that all API Route Handlers have auth checks.

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

Expectation:
- All Route Handlers have a getUser() auth check
- Critical endpoints (login, signup, reset) have rate limiting

Risk: Open API endpoints are the most common cause of security issues. Without rate limiting, brute-force attacks are possible.

---

## B6: Rate Limiting Implemented

Verify that rate limiting is in place.

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

Expectation:
- Rate limiting package installed (e.g., @upstash/ratelimit or custom implementation)
- Rate limiting active on: login, signup, password reset endpoints

Risk: Without rate limiting on login, an attacker can test thousands of password combinations per minute.

---

## B7: Logging Without Secrets

Verify that logs do not contain sensitive data.

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

Expectation:
- No console.log with user data, tokens, or secrets
- Ideally structured logging with redaction

Risk: Logs in monitoring systems are visible to many people. User data in logs = privacy compliance issue.

---

## C1: Dependency Updates

Verify that dependencies are up to date and secure.

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

Expectation:
- npm audit: no high/critical findings
- @supabase/ssr up to date
- Next.js on current patch level

Risk: Known vulnerabilities in outdated packages.

---

## Summary

Now produce a summary in the following format:

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

## Result

PASS:     X of Y checks
WARNING:  X checks
CRITICAL: X checks

## Critical Findings (act immediately)
- ...

## Warnings (resolve this week)
- ...

## Passed
- ...

## Recommended Next Steps
1. ...
2. ...
3. ...
```

Prioritize strictly: Critical findings first, then warnings.
For each finding: What is the problem, why is it a risk, what is the fix.
