CORS (Cross-Origin Resource Sharing) è un meccanismo basato su header HTTP che permette a un server di indicare al browser quali origini esterne sono autorizzate a leggere le risorse che espone. È l’estensione ufficiale e controllata della Same-Origin Policy: quando un’applicazione frontend su https://app.it deve chiamare un’API su https://api.altro.it, è CORS che regola se la risposta può essere letta.
CORS è interamente applicato dal browser: i server non partecipanti semplicemente non inviano gli header CORS, e il browser blocca la lettura della risposta lato client. Le chiamate server-to-server non sono soggette a CORS.
Richieste semplici e preflight
Richieste semplici (simple requests)
Una richiesta cross-origin è considerata “semplice” se soddisfa tutte queste condizioni:
- Metodo:
GET,HEADoPOST. - Header standard: nessun header custom oltre a
Accept,Content-Type(solo alcuni valori),Accept-Language. Content-Type(se POST):application/x-www-form-urlencoded,multipart/form-dataotext/plain.
Per le richieste semplici, il browser invia direttamente la richiesta con l’header Origin e verifica se la risposta contiene Access-Control-Allow-Origin.
Richieste con preflight
Per richieste che non soddisfano i criteri sopra (es. PUT, DELETE, Content-Type: application/json, header custom come Authorization), il browser invia prima una richiesta OPTIONS di preflight:
OPTIONS /api/dati HTTP/1.1
Origin: https://app.it
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization
Il server risponde con i permessi:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.it
Access-Control-Allow-Methods: GET, PUT, POST
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
Solo se il preflight ha successo, il browser invia la richiesta effettiva.
Header CORS fondamentali
| Header | Direzione | Significato |
|---|---|---|
Access-Control-Allow-Origin | Risposta | Origini autorizzate (* o URL specifica) |
Access-Control-Allow-Methods | Risposta | Metodi HTTP consentiti |
Access-Control-Allow-Headers | Risposta | Header della richiesta consentiti |
Access-Control-Allow-Credentials | Risposta | Se i cookie/auth possono essere inclusi |
Access-Control-Max-Age | Risposta | Durata cache del preflight (secondi) |
Access-Control-Expose-Headers | Risposta | Header della risposta accessibili a JS |
Origin | Richiesta | Origine del richiedente |
Access-Control-Request-Method | Preflight | Metodo che si intende usare |
Access-Control-Request-Headers | Preflight | Header che si intendono inviare |
Credenziali e cookie
Per default, le richieste cross-origin non includono cookie o header Authorization. Per abilitarli, servono due condizioni:
- Lato client:
credentials: 'include'nella chiamata Fetch (owithCredentials: truein XHR). - Lato server:
Access-Control-Allow-Credentials: trueeAccess-Control-Allow-Originnon può essere*— deve essere un’origine specifica.
Errori di configurazione comuni
Access-Control-Allow-Origin: * con credenziali
Il wildcard * non può coesistere con Access-Control-Allow-Credentials: true. Il browser rifiuta la risposta. Alcuni server gestiscono erroneamente questo caso inviando entrambi — il browser blocca ugualmente, ma il server si comporta come se avesse concesso l’accesso.
Riflessione cieca dell’Origin
Una configurazione pericolosissima:
# Sbagliato — riflette qualsiasi Origin ricevuta
response.headers['Access-Control-Allow-Origin'] = request.headers.get('Origin')
response.headers['Access-Control-Allow-Credentials'] = 'true'
Questo equivale a * ma con credenziali abilitate — qualsiasi origine può fare richieste autenticate. Un attaccante su https://evil.it può leggere le risorse dell’API con i cookie della vittima.
null come Origin consentita
Access-Control-Allow-Origin: null consente richieste da pagine locali (file://), sandbox iframe, e redirect cross-origin — tutte situazioni potenzialmente controllabili dall’attaccante.
Validazione parziale dell’Origin
# Vulnerabile: "maliciosoesempio.it" supera il controllo
if origin.endswith('esempio.it'):
allow_origin(origin)
La validazione deve verificare l’intera stringa dell’origine contro una lista bianca esplicita.
CORS come misura di sicurezza
CORS non è una misura di autenticazione — protegge la lettura della risposta nel browser, non l’accesso al server. Un server con CORS permissivo è comunque vulnerabile a richieste dirette (curl, Postman, server malevolo). La vera protezione delle risorse richiede autenticazione e autorizzazione server-side indipendenti da CORS.
Relazione con altri meccanismi
- Same-Origin Policy — la politica che CORS estende.
- CSRF — CORS non previene CSRF: le richieste semplici (GET, POST form) sono inviate senza preflight.
- Content Security Policy — complementare: CSP controlla cosa la pagina può caricare, CORS controlla cosa il server concede di leggere.