// VULNERABIL - evită asta în PR-uri!
const badSearch = await prisma.$queryRawUnsafe(
`SELECT * FROM User WHERE name LIKE '%${userInput}%'`
);
// OK - Parametrizat corect prin tagged templates
const goodSearch = await prisma.$queryRaw`
SELECT * FROM User WHERE name LIKE ${`%${userInput}%`}
`;Să fim sinceri, Next.js ne-a luat multe griji de pe cap în ultimii ani, mai ales de când Server Components au devenit norma. Asta nu înseamnă că suntem imuni la prostii în 2026, iar la code review încă văd aceleași vulnerabilități clasice trecute cu vederea. Am făcut recent un audit intern pe un proiect cu vreo 12k useri activi și am rămas mască de ce am găsit prin PR-uri vechi, aprobate pe fugă de oameni care credeau că framework-ul rezolvă tot.
Nu e nevoie să fii specialist în securitate ca să prinzi problemele astea. Trebuie doar să știi unde să te uiți când colegii tăi trimit cod spre review.
1. Server Actions și mitul „e protejat automat de CSRF”
Next.js vine cu protecție încorporată împotriva CSRF pentru Server Actions, verificând headerul Origin. Sună bine pe hârtie. Totuși, am pățit ca un coleg să configureze greșit allowedOrigins în next.config.js pentru a rezolva rapid o problemă de CORS cu un subdomeniu de staging. Rezultatul? Am deschis ușa larg pentru atacuri cross-site pe producție.
La PR review, dacă vezi modificări în configurația de rețea sau CORS, deschide bine ochii. De asemenea, dacă folosiți rute API clasice (/api/route.ts) în loc de Server Actions pentru integrare cu terți, acelea nu au protecție CSRF implicită. Acolo ai nevoie de token-uri anti-CSRF clare sau validare strictă de SameSite pe cookie-uri. Fără ele, ești expus.
2. XSS-ul modern în Server Components
Mulți cred că dacă folosesc React, XSS-ul e istorie. Greșit. Încă avem dangerouslySetInnerHTML. Cel mai des îl văd introdus când integrăm un CMS sau când randăm comentarii formatate de utilizatori.
La un proiect trecut, am găsit o vulnerabilitate unde salvam HTML-ul direct în baza de date fără sanitizare, mizând pe faptul că „sanitizăm noi la randare”. Ghici ce? Cineva a uitat să folosească dompurify pe o pagină nouă de detalii. Regula mea de aur în PR-uri: orice linie care conține dangerouslySetInnerHTML trebuie să aibă deasupra o funcție de sanitizare (cum ar fi isomorphic-dompurify). Dacă nu o are, PR-ul primește reject instant. Nu mergem pe încredere.
3. SQL Injection prin „scurtături” în ORM-uri
Aveam impresia că dacă folosim Prisma sau Drizzle suntem protejați complet de SQL injection. Teoretic da. Practic, când baza de date începe să gâfâie sub trafic și ai nevoie de optimizări complexe, apare tentația query-urilor brute.
Am văzut asta acum câteva luni. Pentru un query complex de căutare, s-a folosit o metodă nesigură de concatenare în loc de template literals parametrizate. Motivul scuzat în PR a fost că „era mai ușor de construit string-ul din UI”. Asta e rețeta perfectă pentru un SQLi clasic.
Ce punem în checklist-ul de PR?
Când fac review pe un branch de Next.js, am trei mari chestii pe care le caut obsesiv:
- Rutele API custom: Au validare de schemă (Zod) pe input? Fără Zod, nu trece de mine.
- Server Actions: Se verifică autorizarea în interiorul acțiunii? Nu te baza doar pe faptul că pagina pe care stă butonul e protejată de middleware-ul de auth. Server Action-ul e un endpoint public, oricine îl poate apela direct prin POST.
- Dependențele: Folosim un scanner automat în CI/CD? Next.js tinde să adune zeci de pachete în arborele de dependințe, iar vulnerabilitățile în pachete terțe sunt calea cea mai simplă de atac.
Trade-off-ul sincer e că Next.js îți dă viteză de dezvoltare, dar împrăștie logica de securitate peste tot: în middleware, în layout-uri, în rute API și direct în Server Actions. E mult mai greu de auditat cap-coadă decât o aplicație Express clasică unde aveai toate rutele și middleware-urile într-un singur loc.
Voi cum gestionați securitatea Server Actions în echipele voastre? Vă bazați exclusiv pe middleware sau duplicați verificările de rol în fiecare acțiune în parte?