CORS (Cross-Origin Resource Sharing)

Indice dei contenuti

    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, HEAD o POST.
    • 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-data o text/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

    HeaderDirezioneSignificato
    Access-Control-Allow-OriginRispostaOrigini autorizzate (* o URL specifica)
    Access-Control-Allow-MethodsRispostaMetodi HTTP consentiti
    Access-Control-Allow-HeadersRispostaHeader della richiesta consentiti
    Access-Control-Allow-CredentialsRispostaSe i cookie/auth possono essere inclusi
    Access-Control-Max-AgeRispostaDurata cache del preflight (secondi)
    Access-Control-Expose-HeadersRispostaHeader della risposta accessibili a JS
    OriginRichiestaOrigine del richiedente
    Access-Control-Request-MethodPreflightMetodo che si intende usare
    Access-Control-Request-HeadersPreflightHeader che si intendono inviare

    Per default, le richieste cross-origin non includono cookie o header Authorization. Per abilitarli, servono due condizioni:

    1. Lato client: credentials: 'include' nella chiamata Fetch (o withCredentials: true in XHR).
    2. Lato server: Access-Control-Allow-Credentials: true e Access-Control-Allow-Origin non 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.

    Ultimo aggiornamento: