CORS troppo aperti nelle API IA: come restringere l'asterisco
L'IA può suggerire Access-Control-Allow-Origin: * per far sparire un errore CORS. Ecco come leggerlo in DevTools e restringerlo su Express e FastAPI.
Se stai assemblando un progetto con l’aiuto dell’IA, prima o poi il browser ti bloccherà con un errore in console: Cross-Origin Request Blocked (o CORS policy).
Incolli l’errore in ChatGPT o Claude e la risposta è spesso immediata: middleware CORS, due righe, errore sparito. Nei boilerplate che ho visto, però, la “cura” tipica può essere aprire tutto con Access-Control-Allow-Origin: * — non perché sia la policy corretta, ma perché fa sparire il blocco in DevTools.
Non è un errore di sintassi: è una policy legittima, usata nel contesto sbagliato. Nell’audit di sicurezza gratuito e nelle 7 falle del codice IA (letture opzionali) restano altri buchi strutturali; qui chiudo solo questo.
Ti mostro come leggerlo in DevTools, quando * è accettabile e come restringerlo su Express e FastAPI senza rompere l’app.
ℹ️ Nota / Prerequisito operativo
Ti servono: frontend + backend che parlano (anche in locale), DevTools del browser e, per il test finale, un terminale concurl. Tieni a portata l’elenco dei domini reali del frontend (produzione +localhostdi sviluppo).
Che cos’è il CORS (in sintesi)
CORS (Cross-Origin Resource Sharing) non è un firewall del server: è una regola che il browser applica alle risposte lette da JavaScript.
Di base il browser impedisce a uno script su https://sito-a.com di leggere la risposta di https://api-b.com. Senza questa restrizione, una pagina malevola in un’altra scheda potrebbe interrogare altre origini usando il contesto del tuo browser (cookie di sessione inclusi, quando le regole lo consentono).
Per allentare il blocco, il backend dichiara chi può leggere la risposta con l’header Access-Control-Allow-Origin. Se il valore è *, sta dicendo: qualsiasi origine web può leggere questi dati via JS nel browser.
⚠️ Attenzione — Cosa CORS non fa
CORS non fermacurl, Postman, bot o un server malevolo che chiama la tua API direttamente. Chiunque può comunque colpire l’endpoint senza browser. Serve autenticazione, autorizzazione e (dove serve) rate limiting. CORS regola soprattutto cosa può fare JavaScript in un browser di un utente.
Quando l’asterisco è un problema
| Scenario d'uso dell'API | Uso di * accettabile? | Perché e cosa comporta |
|---|---|---|
| Asset pubblici statici Immagini, font, CSS pubblici | Sì | Dati pubblici senza autenticazione. Chiunque può includerli; non ci sono segreti utente nella risposta. |
| API pubbliche in sola lettura Cataloghi aperti, meteo, open data | Dipende | Utile se vuoi che altri siti le consumino dal browser. Controlla gli abusi con rate limiting e quote. |
| API con dati utente o autenticazione Dashboard, account, cookie/token | No | Qualsiasi sito può far leggere al browser dell'utente (via JS) risposte che il tuo backend ha autorizzato come pubbliche per tutte le origini. Con cookie/token la posta in gioco sale. |
🚨 Avviso critico — Credenziali e asterisco
Lo standard CORS vieta di combinareAccess-Control-Allow-Origin: *conAccess-Control-Allow-Credentials: true. Se l’IA ti ha generatoallow_origins=["*"]eallow_credentials=True(tipico in FastAPI), i browser moderni rifiutano comunque le richieste con credenziali — oppure, se togli i credentials e lasci solo*, stai aprendo le risposte a ogni origine. Per API con sessione/cookie: whitelist di origini esatte +credentials: true, mai*.
CORS non sostituisce SameSite sui cookie né la protezione CSRF lato server: sono controlli diversi. Qui chiudo solo la policy Origin troppo larga.
Come leggere gli header in DevTools
Windows — Chrome o Edge (percorso principale)
- Apri l’app nel browser e fai login se serve.
- Premi F12 (o clic destro → Ispeziona).
- Scheda Network (Rete). Se è vuota, ricarica la pagina (
Ctrl+R). - Filtra per Fetch/XHR se la lista è rumorosa.
- Esegui l’azione che chiama l’API (click, submit, reload).
- Clicca la richiesta verso il backend.
- Pannello Headers → sezione Response Headers.
- Cerca
access-control-allow-origin. Se vedi*, il backend sta autorizzando qualsiasi origine.
macOS — Chrome / Edge / Safari
- Chrome/Edge: ⌘⌥I o F12 → Network → stessa lettura degli header.
- Safari: attiva Sviluppo (Impostazioni → Avanzate), poi Ispeziona → Rete → seleziona la richiesta → header di risposta.
Linux — Chrome / Firefox
F12 → Network / Rete → stessa procedura. Su Firefox la scheda si chiama spesso Rete; gli header di risposta sono sotto la richiesta selezionata.
💡 Consiglio pratico — Richiesta OPTIONS
Spesso compare una richiesta gemella con metodo OPTIONS (preflight): il browser chiede permesso prima di POST/PUT “non semplici”. Controlla anche lìAccess-Control-Allow-OrigineAccess-Control-Allow-Methods.
Come restringere il CORS in Express (Node.js)
Pattern pigro tipico:
const express = require('express');
const cors = require('cors');
const app = express();
// Genera Access-Control-Allow-Origin: *
app.use(cors());
Fix: passa un’origine (o una funzione di whitelist). Un’origine = protocollo + host + porta, senza path (https://www.tuosito.com, non https://www.tuosito.com/dashboard).
const express = require('express');
const cors = require('cors');
const app = express();
const whitelist = [
'https://www.tuosito.com',
'https://tuosito.com',
'http://localhost:3000', // solo in sviluppo
];
const corsOptions = {
origin: function (origin, callback) {
// Richieste senza Origin (curl, server-to-server): spesso le lasci passare.
// Dal browser, Origin è sempre presente nelle chiamate cross-origin.
if (!origin || whitelist.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Non consentito dalla policy CORS'));
}
},
// Se il frontend usa fetch(..., { credentials: 'include' }) con cookie:
// credentials: true,
};
app.use(cors(corsOptions));
ℹ️ Nota / Prerequisito operativo
Concredentials: 'include'nel frontend devicredentials: truenel middleware e un’origine concreta (mai*). Dopo il deploy, togli dalla whitelist ilocalhostche non ti servono più in produzione (o usa variabili d’ambiente diverse per dev/prod).
Se usi npm per aggiungere il pacchetto e non ce l’hai:
Windows
npm install cors
npm list cors
macOS / Linux — stessi comandi npm install cors e npm list cors dal Terminale nella root del progetto.
Come restringere il CORS in FastAPI (Python)
Pattern pigro frequente (e spesso incoerente con lo standard):
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # problema
allow_credentials=True, # incompatibile con *
allow_methods=["*"],
allow_headers=["*"],
)
Versione ristretta:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = [
"https://www.tuosito.com",
"https://tuosito.com",
"http://localhost:8000", # solo test locali
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["Content-Type", "Authorization"],
)
Riavvia l’app (uvicorn/gunicorn o il comando che usi) dopo la modifica. In produzione togli localhost dalla lista o caricala da env (CORS_ORIGINS=https://tuosito.com,https://www.tuosito.com).
Test finale prima e dopo
Dal terminale simula un’origine estranea con un preflight OPTIONS.
Windows (Prompt / PowerShell / Windows Terminal)
curl -i -X OPTIONS ^
-H "Origin: https://sito-estraneo.example" ^
-H "Access-Control-Request-Method: POST" ^
https://api.tuosito.com/endpoint
In PowerShell moderno puoi usare la stessa riga su una sola linea:
curl -i -X OPTIONS -H "Origin: https://sito-estraneo.example" -H "Access-Control-Request-Method: POST" https://api.tuosito.com/endpoint
macOS / Linux
curl -i -X OPTIONS \
-H "Origin: https://sito-estraneo.example" \
-H "Access-Control-Request-Method: POST" \
https://api.tuosito.com/endpoint
Cosa cercare nella risposta
- Non deve comparire
Access-Control-Allow-Origin: https://sito-estraneo.example. - Non deve comparire
Access-Control-Allow-Origin: *(se hai stretto la policy). - Poi ritesta dall’app reale in DevTools: la tua origine in whitelist deve ricevere
Access-Control-Allow-Origin: https://www.tuosito.com(o il dominio esatto che hai autorizzato), e l’app deve continuare a funzionare.
Se l’app si rompe dopo il fix, di solito manca un dominio in whitelist (www vs non-www, http vs https, porta di Vite/Next in locale). Aggiungi solo quell’origine, non tornare a *.
Domande Frequenti (FAQ)
Cos’è CORS e perché l’IA può suggerire Access-Control-Allow-Origin: *?
CORS (Cross-Origin Resource Sharing) decide se JavaScript di un’origine può leggere le risposte di un’API su un’altra origine. L’asterisco sblocca quasi ogni sito in un colpo solo: l’IA può proporlo perché fa sparire l’errore in DevTools al primo tentativo — non perché sia la policy corretta in produzione.
Quando Access-Control-Allow-Origin: * è davvero pericoloso?
È un problema quando l’API espone dati sensibili o azioni autenticate e un sito malevolo può far eseguire al browser dell’utente loggato richieste cross-origin leggibili. Per API pubbliche solo-lettura senza cookie, l’impatto può essere minore — ma in un login o in un backend “personale” messo online, meglio una whitelist esplicita.
Come verifico gli header CORS nel browser?
Apri DevTools → scheda Network, ricarica la pagina o ripeti la chiamata API, seleziona la richiesta e guarda Response Headers (e la preflight OPTIONS se c’è). Controlla Access-Control-Allow-Origin, Access-Control-Allow-Credentials e i metodi/header consentiti.
Come restringo il CORS in Express o FastAPI senza rompere il frontend?
Elenca solo le origini reali del tuo frontend (schema + dominio + porta, www vs non-www). Su Express usa un middleware CORS con origin array/callback; su FastAPI configura CORSMiddleware con la stessa whitelist. Dopo il fix, ritesta: l’origine autorizzata deve funzionare, un’origine estranea no.
CORS sostituisce autenticazione, cookie sicuri o un firewall?
No. Restringere l’asterisco limita cosa può leggere JavaScript cross-origin; non autentica i client, non nasconde l’API a chi la chiama fuori dal browser e non sostituisce flag come HttpOnly / SameSite sui cookie di sessione.
Cosa resta fuori da CORS
Restringere l’asterisco riduce ciò che JavaScript cross-origin può leggere nel browser. Non autentica i client, non nasconde l’API a chi la chiama fuori dal browser e non sostituisce cookie HttpOnly / SameSite (vedi la guida opzionale sui cookie di sessione sicuri).
Cinque minuti di whitelist esplicita, in produzione, chiudono uno dei “fix veloci” più comuni del vibe coding — senza togliere all’app la possibilità di parlare col proprio frontend.