Common Security Mistakes
Common Security Mistakes
Section titled “Common Security Mistakes”Introduction
Section titled “Introduction”This topic covers the most common security mistakes in Next.js applications. Avoiding these will prevent the majority of security issues.
Top Mistakes
Section titled “Top Mistakes”1. Storing Secrets in Client Code
Section titled “1. Storing Secrets in Client Code”// ❌ WRONG — visible in browserconst API_KEY = 'sk_live_abc123'fetch(`/api/data?key=${API_KEY}`)
// ✅ CORRECT — server-side only// app/api/proxy/route.tsexport async function GET() { const data = await fetch('https://api.example.com/data', { headers: { Authorization: `Bearer ${process.env.API_KEY}` } })}2. Trusting User Input Without Validation
Section titled “2. Trusting User Input Without Validation”// ❌ WRONG — vulnerable to injectionapp.get('/users', (req, res) => { db.query(`SELECT * FROM users WHERE id = ${req.params.id}`)})
// ✅ CORRECT — parameterized querydb.user.findUnique({ where: { id: req.params.id } })3. No Rate Limiting on Auth Endpoints
Section titled “3. No Rate Limiting on Auth Endpoints”Without rate limiting, attackers can brute force passwords or abuse API endpoints. Always rate limit login, registration, and public API routes.
4. Returning Detailed Error Messages
Section titled “4. Returning Detailed Error Messages”// ❌ WRONG — gives away informationreturn { error: 'User with email test@example.com not found' }return { error: 'Wrong password for email test@example.com' }
// ✅ CORRECT — generic messagereturn { error: 'Invalid email or password' }5. Missing Security Headers
Section titled “5. Missing Security Headers”export function middleware() { const response = NextResponse.next()
response.headers.set('X-Frame-Options', 'DENY') response.headers.set('X-Content-Type-Options', 'nosniff') response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin') response.headers.set('Strict-Transport-Security', 'max-age=31536000')
return response}6. CORS Misconfiguration
Section titled “6. CORS Misconfiguration”// ❌ WRONG — allows any originAccess-Control-Allow-Origin: *
// ✅ CORRECT — restrict to your domainAccess-Control-Allow-Origin: https://yourdomain.com7. Exposing Stack Traces
Section titled “7. Exposing Stack Traces”// ❌ WRONG — exposes internal details in productionreturn NextResponse.json({ error: err.stack }, { status: 500 })
// ✅ CORRECT — log internally, return generic messageconsole.error('API Error:', err)return NextResponse.json({ error: 'Internal server error' }, { status: 500 })Security Checklist
Section titled “Security Checklist”- No secrets in client code or Git history
- All user input is validated with Zod
- Rate limiting is configured on auth endpoints
- Error messages are generic
- Security headers are set
- CORS is restricted to known origins
- Stack traces are never exposed to clients
Summary
Section titled “Summary”Most security issues come from a handful of common mistakes — trusting user input, exposing secrets, missing rate limiting, and returning detailed errors. Follow the checklist to avoid the most critical vulnerabilities.