Sicurezza di siti e app IA

Cookie di sessione sicuri: i flag che l'IA può omettere nei progetti web

9 min di lettura
Laptop su scrivania scura: DevTools Cookies con Secure e HttpOnly evidenziati in arancione e SameSite Lax
Windows macOS Linux
Immagine generata: Alex Lunalbi · Gemini · ai riparo

Generare un login con l'IA è facile, ma i flag HttpOnly, Secure e SameSite possono mancare. Come verificarli in DevTools e chiederli correttamente.

Quando chiedi a un’intelligenza artificiale di scriverti un sistema di login per la tua nuova app web, il risultato di solito funziona al primo colpo: l’utente inserisce la password, il server valida i dati, restituisce un cookie di sessione e l’utente risulta loggato.

C’è però una fallacia tipica del vibe coding (creare software delegando la logica all’IA): il modello può scrivere il minimo necessario per far funzionare l’app e omettere le configurazioni di sicurezza se non le chiedi in modo esplicito. Nei boilerplate che ho rivisto, i cookie di sessione escono così “nudi”, senza le protezioni di base.

Un cookie senza i flag giusti può diventare un bersaglio comodo per lo XSS (Cross-Site Scripting): se uno script malevolo gira nella tua pagina, può leggere il cookie (se non è HttpOnly) e rubare la sessione, scavalcando la password.

In questo articolo ti mostro come controllare i cookie in DevTools (partendo da Windows), cosa fanno HttpOnly, Secure e SameSite, e come farli scrivere correttamente all’IA in Express, Flask e Next.js.

ℹ️ Nota / Prerequisito operativo
Ti serve un browser moderno (Chrome, Edge, Firefox o Safari) e un’app web locale o remota su cui fare login e ispezionare i cookie. Non serve un tool esterno.

Se stai ancora mappando le falle tipiche del codice generato dall’IA, l’audit di sicurezza gratuito e le 7 falle comuni restano letture opzionali: qui mi concentro solo sullo storage della sessione nel browser.

Prima di toccare il codice, ispeziona cosa sta davvero emettendo la tua app. Basta il browser.

Windows — Chrome o Edge (percorso principale)

  1. Apri l’app nel browser e fai il login (es. http://localhost:3000 o il tuo dominio di staging).
  2. Premi F12 (oppure clic destro sulla pagina → Ispeziona).
  3. Apri la scheda Application (Applicazione). Se non la vedi, clicca » nella barra delle schede.
  4. Nella colonna di sinistra, sotto Storage, espandi Cookies e seleziona il dominio dell’app (es. http://localhost:3000).
  5. Nella tabella a destra cerca le colonne HttpOnly, Secure e SameSite sul cookie di sessione (spesso session, session_id, sid, connect.sid, ecc.).
  6. Cosa cercare: HttpOnly spuntato / true; Secure true in HTTPS di produzione; SameSite almeno Lax (o Strict se lo hai scelto di proposito). Celle vuote o None senza motivo = da correggere.

macOS — Chrome o Edge

Stessi passi di Windows (F12 o clic destro → Ispeziona → Application → Cookies). Su Mac, se F12 non apre DevTools in Chrome, usa ⌘⌥I o il menu Visualizza → Opzioni per sviluppatori → Strumenti per sviluppatori.

macOS — Safari

  1. Attiva il menu Sviluppo: Safari → Impostazioni → Avanzate → Mostra menu Sviluppo nella barra dei menu.
  2. Clic destro sulla pagina → Ispeziona elemento (oppure menu Sviluppo → Mostra Web Inspector).
  3. Scheda Archiviazione → Cookie → dominio dell’app.
  4. Controlla le colonne relative a HttpOnly, Secure e SameSite (le etichette possono variare leggermente rispetto a Chrome).

Linux — Chrome / Chromium / Firefox

  • Chrome/Chromium: F12 → Application → Cookies (come su Windows).
  • Firefox (anche su Windows/macOS): F12 → scheda Archiviazione (Storage) → Cookie → dominio. Controlla HttpOnly, Secure e SameSite sulla riga del cookie di sessione.
Chrome DevTools Network: Set-Cookie con flag Secure, HttpOnly e SameSite=None e avviso cookie bloccati
In DevTools (scheda Network → Headers) il Set-Cookie mostra i flag Secure, HttpOnly e SameSite: così controlli se il server li ha emessi, anche quando il browser segnala cookie bloccati.

💡 Consiglio pratico
Per il test usa localhost o uno staging. Non fotografare / condividere screenshot con token reali di produzione: il valore del cookie è la sessione.

Ogni cookie può portare “istruzioni” al browser. Se non le imposti, restano i default, spesso più permissivi del necessario.

Flag cookie Cosa mitiga Perché serve in pratica
HttpOnly Isolamento da JavaScript Furto cookie via XSS Il cookie non è leggibile da document.cookie. Uno script XSS non può estrarre il token di sessione e inviarselo altrove. Non elimina l’XSS in sé.
Secure Solo su HTTPS Sniffing su rete Il browser invia il cookie solo su connessioni HTTPS. Riduce il rischio di intercettazione su Wi‑Fi pubbliche. Non è una difesa anti-XSS.
SameSite Contesto della richiesta CSRF (non XSS) Decide se il cookie parte anche da richieste cross-site. Utile contro CSRF. Non ferma uno script che gira già sulla tua pagina (XSS).

HttpOnly: il blocco sul furto della sessione via script

Se ne scegli uno solo per i cookie di sessione, è questo. HttpOnly dice al browser: questo cookie parla col server; JavaScript della pagina non lo legge e non lo modifica.

Senza HttpOnly, chi inietta codice (es. campo commenti non filtrato) può usare document.cookie, estrarre il token e mandarselo su un server proprio.

⚠️ Attenzione — SPA e JWT
Se l’IA ha messo il JWT in localStorage o in un cookie leggibile da JS per poi copiarlo in un header Authorization, HttpOnly “rompe” quel flusso. Non è un buon motivo per togliere il flag: la raccomandazione tipica (anche in linea con le linee guida OWASP sull’auth basata su cookie) è far gestire la sessione al browser con cookie HttpOnly, senza che il frontend manipoli il token. Tenere i JWT accessibili a JS aumenta la superficie XSS.

Secure: solo su connessioni cifrate

Con Secure, su HTTP in chiaro il browser non allega il cookie. In produzione, su HTTPS, è praticamente obbligatorio per le sessioni.

Su localhost i browser moderni spesso accettano cookie Secure anche su HTTP: comodo in sviluppo, ma non farti ingannare — in produzione senza HTTPS il flag Secure è indispensabile (e senza HTTPS hai già altri problemi).

SameSite: non è un antivirus

Valori tipici:

  • Lax — il cookie parte sulle navigazioni top-level (es. click su un link verso il tuo sito). Buon default per molte app.
  • Strict — solo se la richiesta nasce dal tuo stesso sito. Più stretto; a volte l’utente deve rifare login arrivando da un link esterno.
  • None — consente l’invio cross-site; richiede anche Secure. Usalo solo se ti serve davvero (es. scenari embed/cross-origin specifici), non “perché l’IA l’ha messo”.

Punto chiave: SameSite non mitiga l’XSS. Se lo script malevolo gira sulla tua origine, la richiesta è same-site e i cookie partono. SameSite aiuta soprattutto contro il CSRF (Cross-Site Request Forgery).

Come impostare i flag nei progetti generati dall’IA

Non chiedere solo «scrivi la login». Nel prompt specifica: «Imposta il cookie di sessione con HttpOnly, Secure (in produzione) e SameSite=Lax». Poi verifica in DevTools dopo il login.

Express (Node.js)

I flag stanno nelle options di res.cookie():

// Esempio in Express.js
app.post('/login', (req, res) => {
  // ... autenticazione e generazione del session_id ...
  const sessionId = 'token-generato-dal-backend';

  res.cookie('session_id', sessionId, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    maxAge: 24 * 60 * 60 * 1000, // 24 ore
  });

  res.send('Login effettuato');
});

💡 Consiglio pratico — locale vs produzione
Con secure: true su HTTP “vero” (es. IP in LAN senza HTTPS) il cookie spesso non viene salvato. Legare secure a NODE_ENV === 'production' (o a una variabile tipo COOKIE_SECURE=true) è un compromesso comune. Dopo il deploy HTTPS, ricontrolla in DevTools che Secure sia true.

Flask (Python)

# Esempio in Flask
from flask import Flask, make_response
import os

app = Flask(__name__)

@app.route('/login', methods=['POST'])
def login():
    # ... validazione utente ...
    session_id = 'token-generato-dal-backend'

    resp = make_response('Login effettuato')
    # In produzione forza True (HTTPS). In locale puoi lasciare False.
    is_secure = os.environ.get('COOKIE_SECURE', '').lower() in ('1', 'true', 'yes')

    resp.set_cookie(
        'session_id',
        session_id,
        httponly=True,
        secure=is_secure,
        samesite='Lax',
        max_age=86400,
    )
    return resp

Se usi anche le sessioni firmate di Flask (session[...]), configura in modo coerente SESSION_COOKIE_HTTPONLY, SESSION_COOKIE_SECURE e SESSION_COOKIE_SAMESITE nell’oggetto app.config, così non dipendi solo da un set_cookie manuale.

Next.js (App Router)

Con cookies() in Server Actions o Route Handlers (Next.js 15+: cookies() è async — va fatto await):

// Esempio in Next.js (app/actions.js)
'use server';

import { cookies } from 'next/headers';

export async function loginAction(formData) {
  // ... logica di validazione ...
  const sessionId = 'token-generato-dal-backend';

  const cookieStore = await cookies();
  cookieStore.set('session_id', sessionId, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    maxAge: 60 * 60 * 24, // 24 ore in secondi
    path: '/',
  });
}

Dopo il login, torna in DevTools e verifica le tre colonne sul cookie appena impostato.

Domande Frequenti (FAQ)

Come minimo: HttpOnly (niente lettura da JavaScript), Secure (solo su HTTPS) e SameSite sensato (Lax o Strict nella maggior parte dei login; None solo se serve davvero cross-site e sempre con Secure). Controlla anche Path e una scadenza coerente.

Apri DevTools → Application (o Archiviazione) → Cookies → seleziona il tuo dominio. Nella tabella cerca le colonne HttpOnly, Secure e SameSite sul cookie di sessione dopo il login. Su Firefox il percorso analogo è Archiviazione → Cookie.

Perché l’IA può omettere HttpOnly, Secure e SameSite nei tutorial di login?

Nei dataset abbondano snippet “che funzionano in locale” su http://localhost senza HTTPS. L’assistente può ripetere il percorso minimo che fa partire la sessione, non la checklist di produzione. Tocca a te aggiungere i flag e verificarli in DevTools dopo ogni modifica.

HttpOnly basta contro gli attacchi XSS?

No. HttpOnly impedisce a uno script malevolo di leggere il cookie e esfiltrarlo facilmente, ma lo script può comunque agire come l’utente loggato (chiamate API, modifiche). Serve anche sanitizzare gli output HTML e, dove puoi, una CSP utile.

SameSite=None è sicuro per ogni sito?

Solo se ti serve davvero cookie cross-site (es. widget su altri domini) e solo insieme a Secure su HTTPS. Per un login classico sullo stesso sito, Lax o Strict riducono meglio il rischio CSRF “da click esterno”.

Limiti: cosa i flag non possono fermare

Cookie ben configurati riducono la superficie di attacco, non rendono il sito invulnerabile.

Nei miei test su progetti vibe-coded, il rischio tipico è la sensazione di «ora è tutto a posto». Con HttpOnly, uno XSS non ruba facilmente il cookie — ma lo script può comunque agire come l’utente loggato: chiamare le API, cambiare dati, leggere ciò che è a schermo. I flag isolano la sessione come segreto nel browser; per ridurre davvero l’XSS servono escaping/sanitizzazione degli output e input controllati (e, a livello di header, anche una CSP sensata — vedi la guida su CSP/HSTS/X-Frame-Options come lettura opzionale).

SameSite non è un antivirus; Secure non sostituisce HTTPS ben configurato; HttpOnly non sostituisce la pulizia dell’HTML. Usali insieme, poi verifica in DevTools dopo ogni modifica della login.

Alex Lunalbi

Alex Lunalbi

Security & privacy

Dona su PayPal

Scrivo di sicurezza digitale pratica e codice IA. Su ai riparo ogni procedura è verificata su macchine reali.

Tag
  • sicurezza,
  • vibe coding,
  • privacy,
  • autenticazione