eduardweb.
Securitate & AuthIntermediar#nextjs#securitate#web-dev#owasp

Securitate în Next.js prin 2026: Dincolo de ce face framework-ul implicit

De Andreea Crăciun, 28 apr. 2026 · 3 vizualizări · 3 like-uri

Postat acum 2 zile
typescript
// Exemplu de ce să NU accepți în PR (vulnerabil la IDOR și SQLi)
export async function deletePost(formData: FormData) {
  const id = formData.get('id');
  // PROBLMĂ: Nu verificăm dacă userul e logat sau e owner
  // PROBLEMĂ: Raw query fără parametrizare corectă
  await db.execute(`DELETE FROM posts WHERE id = ${id}`);
}

// Varianta corectă
const DeleteSchema = z.object({ id: z.string().uuid() });

export async function deletePostSafe(data: unknown) {
  const session = await auth();
  if (!session) throw new Error("Neautorizat");

  const { id } = DeleteSchema.parse(data);
  
  // Verificăm ownership-ul înainte de ștergere
  const post = await db.query.posts.findFirst({ 
    where: and(eq(posts.id, id), eq(posts.authorId, session.user.id)) 
  });

  if (!post) throw new Error("Postarea nu există sau nu ai drepturi");

  await db.delete(posts).where(eq(posts.id, id));
}

Next.js ne-a vândut ideea că e un framework sigur „out of the box”, dar în 2026 realitatea e că atacurile s-au mutat mai sus pe stack. Nu mai vorbim de script kiddies care injectează <script>alert(1)</script> în formulare, ci de exploatarea Server Actions și a logicii de hidratare. Dacă dai approve la un PR doar pentru că „trece testele de CI”, s-ar putea să ai o surpriză neplăcută la următorul audit.

Server Actions sunt noile API-uri (și tot așa de vulnerabile)

De când Server Actions au devenit standard, am observat o relaxare periculoasă. Lumea uită că, sub capotă, un Server Action e tot un endpoint HTTP POST. Am pățit la un proiect cu vreo 12k useri să găsesc o acțiune de „delete comment” care primea doar ID-ul comentariului, fără să verifice dacă userul logat e chiar autorul.

În 2026, Broken Access Control (A01 în OWASP) rămâne principala gaură în Next.js. Framework-ul nu știe cine are voie să execute o acțiune doar pentru că ai pus-o într-o componentă protejată vizual. Trade-off-ul e clar: ai viteză de dezvoltare imensă, dar trebuie să scrii manual logica de autorizare în fiecare funcție care are "use server". Dacă nu vezi un check de sesiune și un check de ownership în primele linii din funcție, dă-i direct Request Changes.

SQL Injection n-a murit, doar s-a deghizat

Chiar dacă majoritatea folosim Prisma sau Drizzle, tentația de a scrie „raw queries” pentru performanță e încă acolo. Am economisit vreo 30% la timpul de execuție pe un raport complex folosind raw SQL, dar prețul a fost paranoia constantă la fiecare PR.

Problema apare când echipa începe să concateneze string-uri pentru clauze WHERE dinamice. În Next.js, fiindcă totul e TypeScript, unii developeri au impresia falsă că tipurile îi protejează. Spoiler: nu o fac. În PR, caută orice utilizare de unsafe_ sau orice query care nu folosește template literals parametrizate oferite de driver-ul de bază de date.

XSS și obsesia pentru performanță

XSS-ul în 2026 e mult mai subtil. Nu mai e vorba doar de input-uri, ci de cum randezi datele venite din surse externe (CMS-uri, API-uri third-party). dangerouslySetInnerHTML e încă „in the wild”. Am văzut cazuri unde, pentru a evita un layout shift sau pentru a procesa Markdown rapid, se sărea peste sanitizare.

Regula mea e simplă: dacă văd dangerouslySetInnerHTML, trebuie să văd și o bibliotecă de sanitizare (gen DOMPurify) rulată strict pe server înainte de hidratare. Altfel, e doar o chestiune de timp până când un script injectat în CMS-ul de marketing ajunge să fure session cookies de la admini.

CSRF și marea confuzie

Next.js are protecție implicită pentru Server Actions verificând header-ul Origin. Sună bine, nu? Problema e că mulți dintre noi avem setup-uri complexe cu proxy-uri, load balancere sau rulăm aplicația în medii unde aceste headere sunt mascate sau modificate.

Am avut un caz unde protecția CSRF a fost dezactivată accidental prin configurarea greșită a unui middleware care făcea bypass la verificări pentru „debug”. Întotdeauna verifică în PR dacă cineva s-a atins de headers sau de configurarea CORS. Dacă aplicația ta e publică, nu lăsa Access-Control-Allow-Origin: * nici măcar „pentru teste”.

Ce cauți, concret, în PR?

Când fac review pe securitate, nu mă uit la stilul codului, ci la fluxul datelor:

  1. Validare la intrare: Există un schema Zod pentru formData? Dacă nu, e risc de injection sau crash.
  2. Autorizare explicită: Există auth() apelat chiar în interiorul Server Action-ului?
  3. Sanitizare la ieșire: Dacă afișăm HTML din DB, e curățat?

Securitatea în Next.js nu e un task pe care îl bifezi o dată, e o stare de alertă constantă la fiecare merge. Voi ce scanere de vulnerabilități rulați în pipeline-ul de CI, sau vă bazați doar pe ochiul format?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.