Security hardening for production readiness
- Add security headers (CSP, HSTS, X-Frame-Options, X-Content-Type-Options, etc.) - Strengthen password requirements (10+ chars, mixed case, numbers) - Increase shared list slug entropy from 4 to 16 bytes - Add rate limiting to login, registration, upload, and restore endpoints - Add file magic number validation for image uploads (JPEG, PNG, WebP, HEIC) - Add CSV row limit (50k) to restore endpoint - Update client-side registration form to match new password policy Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import GitHub from "next-auth/providers/github"
|
||||
import Credentials from "next-auth/providers/credentials"
|
||||
import { PrismaAdapter } from "@auth/prisma-adapter"
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { rateLimit } from "@/lib/rate-limit"
|
||||
|
||||
const providers = [
|
||||
Google({
|
||||
@@ -25,6 +26,10 @@ const providers = [
|
||||
const password = credentials?.password as string
|
||||
if (!email || !password) return null
|
||||
|
||||
// Rate limit: 10 login attempts per email per 15 minutes
|
||||
const rl = rateLimit(`login:${email.toLowerCase()}`, 10, 15 * 60 * 1000)
|
||||
if (!rl.success) return null
|
||||
|
||||
const user = await prisma.user.findUnique({ where: { email } })
|
||||
if (!user || !user.password) return null
|
||||
|
||||
|
||||
@@ -652,7 +652,7 @@ export async function executeRestore(
|
||||
.map((oldId) => drinkIdMap.get(oldId))
|
||||
.filter(Boolean) as string[]
|
||||
|
||||
const slug = crypto.randomBytes(6).toString("hex")
|
||||
const slug = crypto.randomBytes(16).toString("hex")
|
||||
|
||||
if (mode === "replace") {
|
||||
await tx.sharedList.create({
|
||||
|
||||
Reference in New Issue
Block a user