Interview Lab handles user credentials, resume content, and interview data. Security is a first-class concern.
- JWT tokens signed with strong secrets (minimum 256 bits)
- Tokens stored in HttpOnly cookies (not localStorage for auth tokens)
- Client-side token caching in localStorage for UI state only
- Token expiration: 7 days, with refresh capability
- Passwords hashed with bcrypt (cost factor 12)
- Server-side auth checks on all protected routes
- Admin routes require
isAdmin: truein user record - Subscription tier checks enforced in API, not just UI
- Rate limiting on auth endpoints (10 attempts per minute)
- Rate-limit identity comes only from Vercel's managed client-IP header or an
explicitly configured trusted reverse-proxy header. Client-supplied
x-forwarded-forandx-real-ipvalues are ignored. - Every session carries the user's current
sessionVersion. Incrementing that value revokes every older token even when its signature and expiry remain valid.POST /api/auth/logout-allperforms this revocation and clears the current session cookie. - State-changing admin content requests require an exact
Originmatch withNEXT_PUBLIC_APP_URLand reject cross-site Fetch Metadata. Production fails closed when the application URL is missing or invalid.
| Data Type | Protection |
|---|---|
| Passwords | bcrypt hashed, never logged or returned |
| JWT Secrets | Environment variable, never committed |
| User Resumes | Isolated by user ID, no public access |
| AI Feedback | Stored with session, user-owned |
| API Keys | Environment variables, server-side only |
Required secrets (never commit to git):
DATABASE_URL # PostgreSQL connection string
JWT_SECRET # min 256-bit random string
NEXT_PUBLIC_APP_URL # Public app URL
TRUSTED_CLIENT_IP_HEADER # Self-hosted trusted proxy only; never x-forwarded-for- No
.envfiles committed - No secrets in code or comments
- No
console.logof sensitive data - Input validation on all API endpoints
- SQL injection prevented via Prisma
- XSS prevented via React's default escaping
- CSRF: admin content mutations have origin/Fetch Metadata enforcement; extend the shared policy to every remaining cookie-authenticated mutation
- Rate limiting on auth endpoints
- Rate limiting on AI endpoints (15 req/min per user)
- Account deletion endpoint (DELETE /api/user/me) — requires password confirmation
- All-session revocation endpoint (
POST /api/auth/logout-all) - Data export endpoint (GET /api/user/me/export) — GDPR data portability
Users can request a full data export via GET /api/user/me/export and permanent
account deletion via DELETE /api/user/me (requires password confirmation in request body).
See docs/07-guardrails.md for AI safety policies:
- No fabrication of experience
- Truthfulness warnings on resume/coach outputs
- Experience labels: "trained on", "basic familiarity", "hands-on experience"
Contact: Report via GitHub Issues with [Security] prefix.