nextjs-security
Use when writing or reviewing any Next.js server code — Route Handlers, Server Actions, middleware, auth, cookies, env vars, headers. Enforces the project's Next.js security checklist.
SKILL.md.claude/skills/nextjs-security/SKILL.md
GitHubNext.js Security
Auth & sessions
- Store session tokens in
httpOnly+Secure+SameSite=Laxcookies, set viacookies()fromnext/headers. Never store session tokens inlocalStorage. - Session timeout ≤ 24h; rotate the session token on any privilege change (login, role change, password reset).
Authorization
- Re-verify auth inside every Route Handler / Server Action, not just in
middleware. Return
401when there is no session,403on a role mismatch. - Middleware is edge routing, not a security boundary. Protect admin/privileged routes both in middleware and in the handler itself.
CVE-2025-29927 (middleware bypass)
- Patch floor: Next.js ≥ 15.2.3. The vulnerability lets an attacker set the
x-middleware-subrequestheader to skip middleware entirely. - This repo currently pins
^15.1.0— below the floor. Flag this whenever touchingnext.config.ts,middleware.ts, or thenextdependency, and treat bumping to ≥ 15.2.3 as a blocking security task, not a nice-to-have.
Input validation
- Validate all
formData/ request bodies server-side with Zod.safeParse(or equivalent) before acting on them. Client-side validation is UX only — never trust it as the security control.
Headers in next.config.ts
Set security headers centrally:
- CSP:
default-src 'self', with a scopedscript-src/connect-src(avoidunsafe-inline/unsafe-evalwhere possible) andframe-ancestors 'none'. X-Frame-Options: DENYX-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originPermissions-Policy— deny camera/microphone/geolocation unless explicitly needed.Strict-Transport-Security(HSTS) in production.
Other hard rules
- Never put secrets in
NEXT_PUBLIC_*env vars — anything with that prefix ships to the browser bundle. Keep.env*files out of version control. - Rate-limit login, OTP, and password-reset endpoints.
- Sanitize or avoid
dangerouslySetInnerHTML; if unavoidable, sanitize withisomorphic-dompurify. - Validate any post-login
returnTo/redirect URL is a relative, same-origin path — never redirect to an unvalidated absolute URL (open-redirect risk). - Run
pnpm auditperiodically and address high/critical findings.
Source: authgear.com/post/nextjs-security-best-practices