Next.js Security
Priority: P0 (CRITICAL)
Workflow: Secure a Next.js App
- Add auth middleware — Create
middleware.tsto verify JWT/session on protected routes. - Validate Server Actions — Parse all inputs with Zod schemas; call
await auth()first. - Set security headers — Add CSP, HSTS, X-Frame-Options in middleware response.
- Use
server-only— Import in modules containing secrets to prevent client bundling. - Taint sensitive objects — Use
taintObjectReferenceto block server objects from reaching client.
Secure Server Action Example
Implementation Guidelines
- Next.js Middleware: Use
middleware.tsfor edge-side authentication, role-based access control (RBAC), and enforcing Security Headers (e.g.,Content-Security-Policy (CSP),X-XSS-Protection). - Server Actions: Always sanitize all inputs from
FormDataor JSON using Zod. Perform authentication checks (await auth()) inside every action to verify the caller. - Data Tainting: Use the
experimental_taintAPI (taintObjectReference) to ensure sensitive server objects (e.g., User withpasswordHash) never leak into a Client Component. - Route Handlers (
route.ts): Implement rate limiting to prevent brute-force or DoS attacks. Verify Origin/Referer headers to mitigate CSRF (Cross-Site Request Forgery). - Auth Tokens: strictly use
HttpOnly,Securecookies withSameSite: 'Lax'for session management. Never store tokens inlocalStorage. - Logic Isolation: use the
server-onlypackage to prevent backend-specific logic from being included in the client bundle. - Component Purity: Escape all user-provided content rendered in components. Never use
dangerouslySetInnerHTMLwithout a sanitizer likeDOMPurify.
Anti-Patterns
- No leaking DB fields to client: Use DTOs; never pass raw model objects.
- No
process.envin client bundles: Mark asNEXT_PUBLIC_only if safe to expose. - No unvalidated Server Action inputs: Always validate with Zod schema.
- No auth checks in shared Layouts: Auth in layouts is insecure; use Middleware.