Web Design and Engineering

Sicurezza server actions Next.js 2026: bypass middleware e fix

Nel 2026 Next.js ha rilasciato 13 advisory su bypass middleware, cache poisoning e SSRF. Ecco cosa è cambiato e come proteggere oggi le server actions.

12 maggio 20267 min di lettura
Sicurezza server actions Next.js 2026: bypass middleware e fix

La sicurezza frontend in Next.js è la disciplina che mette in sicurezza server actions, middleware, server components e comportamento della cache così che una route UI non possa diventare un data leak non autenticato o un vettore di denial of service. Nel 2026 la superficie d'attacco è diversa rispetto al 2023 perché tre delle feature più usate del framework siedono ora sul percorso critico delle decisioni di autorizzazione: middleware, server actions e cache dei React Server Components.

Solo nel 2026 Vercel ha coordinato una release che ha corretto 13 advisory separati tra bypass middleware, server-side request forgery, cross-site scripting e cache poisoning nell'App Router. Le versioni con la fix sono Next.js 15.5.16 e 16.2.5 (Vercel changelog, maggio 2026). Se la vostra applicazione è stata avviata prima di maggio 2026 e non è stata aggiornata, ogni sezione qui sotto vi riguarda subito.

Perché è più difficile di quanto sembri

Tra Next.js 13 e 16 sono cambiate due cose che hanno silenziosamente spostato la responsabilità della sicurezza. Primo, le server actions sono diventate la superficie di mutazione di default, sostituendo il layer di API route dove vivevano i controlli di autorizzazione. Secondo, il middleware è diventato il layer di autorizzazione di default per le applicazioni App Router, sostituendo i guard per-route sulle pagine protette. Entrambi i cambi sono vincenti dal punto di vista ergonomico. Entrambi trasformano un singolo uso scorretto in un bypass completo.

CVE-2025-29927, divulgata a marzo 2025, è stata l'avvertimento. Il layer del middleware si fidava di un header interno (x-middleware-subrequest) senza verificarne l'origine. Qualsiasi richiesta esterna che falsificasse l'header saltava completamente il middleware, annullando ogni controllo di autorizzazione scritto lì. CVSS 9.1, versioni colpite fino alla 12.x (advisory Snyk). Le applicazioni ospitate su Vercel e Netlify erano protette a livello edge. Quelle self-hosted sono rimaste esposte fino alla patch.

La release di maggio 2026 ha aggiunto altri tre advisory di bypass del middleware, questa volta su URL .rsc e di segment-prefetch nell'App Router. Un URL di prefetch costruito ad arte poteva risolvere alla stessa pagina senza essere intercettato dalla regola middleware prevista, garantendo di nuovo accesso a contenuti protetti (Netlify security update, maggio 2026).

La soluzione ovvia che da sola non basta

Il riflesso è centralizzare l'autorizzazione nel middleware. Sembra pulito: un file, un solo posto dove leggere chi può fare cosa. Il difetto è che il middleware gira al livello di routing, non al livello dei dati. Tutto ciò che bypassa il routing, sia tramite una CVE, un proxy mal configurato, un pattern di route non matchato, o un percorso di prefetch statico, bypassa anche la vostra autorizzazione. La guida ufficiale di Vercel è oggi esplicita: il middleware va usato per controlli ottimistici (redirect, rilevamento locale), e l'autorizzazione vera vive accanto ai dati (guida autenticazione Next.js).

Cosa funziona davvero nel 2026

Trattate ogni server action come una public API route

Una server action è chiamabile da qualsiasi client che conosce l'ID dell'action. La difesa CSRF del framework confronta gli header Origin e Host e rifiuta i mismatch, bloccando i classici form post cross-origin (blog sicurezza Next.js). Ma non controlla chi è il chiamante. Ogni action che pubblicate ha bisogno di tre controlli in ordine: validazione dell'input (Zod o Valibot), autenticazione (è una sessione loggata), autorizzazione (questo utente può agire su questa specifica risorsa). Saltatene anche solo uno e avete una mutazione non autenticata in produzione.

Consolidate l'accesso ai dati in un DAL

Il pattern Data Access Layer è l'unico pezzo di architettura che sopravvive sistematicamente ai bump di versione di Next.js. Ogni lettura e ogni mutazione passa per un singolo modulo che riceve la sessione corrente e la risorsa richiesta in input, e restituisce o i dati o una risposta negata. Server actions e server components chiamano entrambi il DAL; nessuno dei due parla direttamente al database. Due vantaggi: la logica di autorizzazione smette di disperdersi tra decine di file di action, e le vostre regole RLS a livello database diventano un controllo di difesa in profondità invece che il primario.

Usate la taint API per gli oggetti ad alto rischio

I metodi experimental_taintObjectReference e experimental_taintUniqueValue di React vi permettono di marcare un oggetto utente o un token così che React rifiuti di serializzarlo nel payload di un Client Component. Attivato tramite experimental.taint in next.config.js, intercetta un'intera classe di esposizioni accidentali in cui un server component passa una riga di database contenente una password hashata o una API key a un componente client figlio (documentazione React). Caveat: il taint traccia gli oggetti per riferimento, quindi uno spread o una copia rimuove il marker dal risultato. È un'ultima linea di difesa, non l'unica.

Mai catturare dati sensibili nei closure delle server actions

Una server action definita dentro un server component può chiudere su variabili locali. Quelle variabili vengono serializzate come parte del payload di trasporto dell'action e diventano visibili a chiunque ispezioni la rete. La regola che applichiamo: le server actions vivono in file "use server" separati, e catturano solo identificatori non sensibili a cui l'utente ha già accesso, come uno slug di URL o un ID pubblico. Tutto ciò che deve essere cercato lato server viene cercato lato server partendo dalla sessione.

Cache poisoning: assumete che il vostro CDN sbaglierà

CVE-2025-49826 è l'esempio più pulito di come i layer di cache e di routing divergono. Una risposta 204 No Content da una route ISR o SSR di Next.js poteva essere cachata da un CDN configurato per cachare le risposte vuote, e una volta cachata, ogni visitatore successivo riceveva una pagina bianca (analisi ZeroPath di CVE-2025-49826). La difesa è duplice: tenete Next.js patchato (15.1.8 o successivo corregge questa specifica CVE), e configurate il CDN per non cachare mai risposte 204 sulle route HTML. Testate con un 204 deliberato da staging e verificate l'header di cache nella risposta.

Allowlist esplicita degli origini, non fidatevi dei default

Le server actions accettano la richiesta solo quando Origin combacia con Host, ma i setup di produzione dietro a un load balancer o a un proxy hanno bisogno che X-Forwarded-Host sia impostato correttamente. Se il vostro reverse proxy lo rimuove, il layer di action ricade sui default e la vostra protezione CSRF diventa inconsistente. Impostate serverActions.allowedOrigins in next.config.js per qualsiasi origine esterna che accettate intenzionalmente, preview deployment inclusi, e auditatelo come parte della checklist di deploy.

Patchate lo stesso giorno, non lo stesso trimestre

La release di maggio 2026 ha riunito 13 fix in due bump di versione. Il tempo medio tra divulgazione e tentativi di exploit per le CVE di Next.js si è ridotto ogni anno dal 2024. CVE-2025-29927 ha avuto proof-of-concept pubblici entro 24 ore dalla divulgazione (Datadog Security Labs). Iscrivetevi agli advisory di sicurezza di vercel/next.js su GitHub, automatizzate le PR di dipendenze tramite Dependabot o Renovate, e spedite le patch di sicurezza lo stesso giorno in cui atterrano.

Come appare nella pratica

Su un progetto SaaS recente abbiamo eseguito l'audit su un'applicazione App Router da 28 route avviata a fine 2024. L'applicazione aveva autorizzazione solo nel middleware, server actions inline nei componenti di pagina, e nessun DAL. Risultati: 12 server actions che non ricontrollavano la sessione, 4 action che catturavano gli ID utente da closure invece che dalla sessione, 1 pagina che passava una riga Supabase completa con una colonna protetta da service-role a un componente client, e un Next.js obsoleto (14.1) esposto alla CVE di bypass middleware.

La sequenza di fix ha richiesto 9 giorni lavorativi: bump di Next.js e React, estrazione di ogni server action in file app/actions/*.ts, introduzione di un DAL con un unico guard requireSession, sostituzione degli ID catturati nei closure con ID derivati dalla sessione, attivazione del taint sugli oggetti utente e tenant, e uno step di CI che fa fallire la build se un file "use server" non importa il DAL. Dopo l'audit, l'applicazione ha superato un pentest esterno con zero rilievi di autorizzazione.

Foto di Jakub Żerdzicki su Unsplash

Studio

Inizia un progetto.

Un partner unico per aziende, PA, startup e SaaS. Produzione più veloce, tecnologie moderne, costi ridotti. Un team, una fattura.