A set of best practices for keeping your Next.js apps secure.
# Next.js Security Best Practices
## Data Validation and Input Handling
- **Always validate user inputs with schemas**
- ❌ Directly using req.body in API handlers without validation
- ✅ Using schema validation libraries to validate request bodies before processing them
- **Sanitize rendered content**
- ❌ Using dangerouslySetInnerHTML with unsanitized content
- ✅ Using a sanitization library to clean HTML or avoiding direct HTML insertion
- **Be careful with dynamic imports**
- ❌ Using unvalidated user input for dynamic imports or file paths
- ✅ Strictly validating and limiting what can be dynamically imported
## API Routes and Server Security
- **Separate API route handlers from page components**
- ❌ Using fetch with sensitive operations directly in client components
- ✅ Creating separate API route handlers and calling them from client components
- **Secure API routes with proper authentication**
- ❌ Creating API routes that don't verify auth status before performing operations
- ✅ Checking auth status at the beginning of API handlers and returning 401/403 when needed
- **Implement proper CSRF protection**
- ❌ Creating custom API endpoints without CSRF tokens for state-changing operations
- ✅ Using form actions with built-in CSRF protection or adding CSRF tokens to custom APIs
- **Use proper error handling in API routes**
- ❌ Returning full error details: `return res.status(500).json({ error: err.stack })`
- ✅ Logging detailed errors server-side but returning generic messages to clients
- **Implement rate limiting**
- ❌ Allowing unlimited requests to sensitive endpoints
- ✅ Using rate limiting middleware or implementing custom rate limiting
## Environment and Configuration Security
- **Use environment variables correctly**
- ❌ Adding API keys with NEXT_PUBLIC_ prefix or hardcoding them in client components
- ✅ Using process.env.API_KEY in server components or API routes only
- **Set appropriate Security Headers**
- ❌ Leaving default security headers without customization
- ✅ Using the Next.js headers configuration to set appropriate security policies
## Data Storage and Transmission
- **Avoid client-side secrets in redirects**
- ❌ Redirecting with sensitive data in query params: `router.push(/success?token=${token})`
- ✅ Using cookies or session storage for sensitive data during redirects
- **Secure cookies configuration**
- ❌ Setting cookies without security attributes
- ✅ Using appropriate httpOnly, secure, and sameSite attributes for sensitive data
## Content and File Security
- **Beware of metadata injection**
- ❌ Using unvalidated user input directly in page metadata
- ✅ Sanitizing or validating any user-provided data used in metadata
- **Secure file uploads**
- ❌ Accepting any file upload without validation
- ✅ Implementing strict validation for file types, sizes, and content
## Advanced Protections
- **Protect against prototype pollution**
- ❌ Deep merging objects from untrusted sources without sanitization
- ✅ Using Object.create(null) or dedicated libraries for safe object merging