CORS: chi può leggere la risposta (non chi può chiamare l'API)
Data Pubblicazione: 20/09/2026 | | Sicurezza

CORS: chi può leggere la risposta (non chi può chiamare l'API)

CORS è un header di risposta. Dice quale origin può leggere. Non chiude l'endpoint. Il jolly non sta con i cookie. Il preflight è un OPTIONS. Un plugin «enable CORS» non è una policy.

Un plugin «abilita CORS» non è una policy. Cross-Origin Resource Sharing è un insieme di header di risposta con cui il server dice al browser quale origin può leggere quella risposta. Non dice chi può chiamare l’URL. La chiamata parte lo stesso. Ciò che il browser nega, se gli header mancano, è consegnare il body a JavaScript.

In breve: Access-Control-Allow-Origin con un origin preciso, o * solo senza credenziali. Cookie e Authorization vogliono Access-Control-Allow-Credentials: true e l’origin eco, non il jolly. Il preflight è un OPTIONS. null non si usa. Verifica del 20 settembre 2026 su MDN e sulla Fetch Standard.

Cosa trovi in questo articolo

  1. Cosa è CORS (e cosa non è un firewall)

  2. Allow-Origin: *, un origin, mai null

  3. Preflight, credenziali, Vary

  4. Errori da evitare

  5. In sintesi

Cosa è CORS (e cosa non è un firewall)

MDN, nella guida Cross-Origin Resource Sharing, parte da un vincolo del browser: una pagina su https://app.example che fa fetch() verso https://api.altro non legge la risposta, a meno che il server di api.altro non lo consenta con gli header CORS. Lo stesso vale per XMLHttpRequest, per i font in @font-face da un altro origin, per le texture WebGL, per le immagini disegnate su canvas con drawImage().

La Fetch Standard, che oggi definisce CORS, distingue due piani. Il browser spedisce la richiesta. Il server la riceve, la esegue, risponde. Se gli header CORS non tornano, JavaScript vede solo un errore. Per ragioni di sicurezza, scrive MDN, i dettagli di quell’errore non sono disponibili allo script: si leggono in console. CORS non è un WAF. Non è HSTS. Non è la CSP. HSTS impedisce di tornare in HTTP sul nome. La CSP limita cosa la pagina può eseguire. CORS limita quale origin può leggere una risposta cross-origin. Tre mestieri. Il plugin che promette tutti e tre è un quarto script.

Questo pezzo sta nel cluster Sicurezza, accanto a Subresource Integrity — che senza CORS sul CDN fallisce — al cookie con SameSite e al mixed content. SRI verifica i byte. SameSite decide se il cookie parte. Mixed content è HTTP su una pagina HTTPS. CORS è chi, in pagina, può leggere la risposta.

Allow-Origin: *, un origin, mai null

L’header Access-Control-Allow-Origin è Baseline, disponibile nei browser da luglio 2015. MDN elenca tre forme. Una sola è quella che si usa in produzione con testa.

ValoreCosa fa il browser
*qualsiasi origin può leggere la risposta. Solo su richieste senza credenziali. Con cookie o Authorization, il jolly produce un errore
un origin preciso (https://app.example)solo quel origin. Se i client sono più di uno, il server deve ecoare l’origin della richiesta, non una lista
nullnon si usa. MDN: documenti data:, file: e iframe sandbox serializzano origin null; un attaccante può costruirne uno ostile

Il jolly sul CDN pubblico di un CSS, senza cookie, è un caso. Lo stesso jolly sull’API che restituisce la sessione è un buco. MDN, sull’header Access-Control-Allow-Credentials: se vale true, Access-Control-Allow-Origin non può essere *. Si rimanda l’origin della richiesta. Si aggiunge Vary: Origin, altrimenti la cache consegna a un secondo origin la risposta pensata per il primo.

Una richiesta «semplice», nel vocabolario dell’obsoleta spec CORS — la Fetch Standard non usa più quel nome — è un GET, HEAD o POST che somiglia a un form HTML 4. Il server deve già difendersi dal CSRF su quei verb. CORS, su quelle, non chiede un OPTIONS: chiede comunque Access-Control-Allow-Origin se lo script deve leggere la risposta. Un form può spedire. JavaScript, senza header, non legge.

Preflight, credenziali, Vary

Se il metodo non è GET/HEAD/POST, o se ci sono header non safelisted — Content-Type: application/json è il caso di scuola — il browser fa prima un OPTIONS. Sull’OPTIONS mette Access-Control-Request-Method e, se serve, Access-Control-Request-Headers. Il server risponde con Access-Control-Allow-Methods, Access-Control-Allow-Headers, eventualmente Access-Control-Max-Age. Poi, se l’OPTIONS torna approvato, parte la richiesta vera. MDN: i fallimenti CORS non arrivano allo script con il codice HTTP; arrivano come network error. Si guarda la console, non il catch che stampa «failed to fetch».

HeaderRuolo
Access-Control-Allow-Originchi può leggere. Un origin, o * senza credenziali
Access-Control-Allow-Credentialstrue se devono partire cookie o HTTP auth. Esclude il jolly
Access-Control-Allow-Methodsmetodi ammessi dopo il preflight
Access-Control-Allow-Headersheader ammessi sulla richiesta vera
Access-Control-Max-Agequanto il browser può cacheare il preflight
Vary: Originobbligatorio se l’Allow-Origin è ecoato: la cache non deve mescolare gli origin

Il plugin che scrive Access-Control-Allow-Origin: * su ogni risposta «per far partire la SPA» risolve la console e apre la lettura a qualunque sito. Se in più mette Allow-Credentials: true, i browser rifiutano la coppia: jolly e credenziali non stanno insieme. Il risultato, in pagina, è lo stesso errore di prima, con una policy peggiore in testa. Non è un’API «aperta in modo sicuro». È un header copiato da un tutorial.

SRI, sul CDN, chiede CORS più crossorigin="anonymous": senza, l’hash non parte. Sta nell’articolo su Subresource Integrity. Lì l’header serve a non filtrare il contenuto dal successo o dal fallimento del load. Qui serve a decidere chi, in JavaScript, vede il JSON. Stesso meccanismo, due intenzioni. Il certificato TLS cifra il transito; non sostituisce CORS.

Errori da evitare

  • Mettere Access-Control-Allow-Origin: * insieme a Allow-Credentials: true: i browser lo rifiutano.

  • Restituire null «perché in locale funzionava»: MDN lo sconsiglia, origin ostili inclusi.

  • Trattare CORS come autenticazione: la richiesta arriva al server anche se lo script non legge la risposta.

  • Dimenticare Vary: Origin quando si ecoa l’origin: la cache mescola le risposte.

  • Confondere CORS con la CSP o con HSTS: tre header, tre mestieri.

  • Fidarsi del plugin «enable CORS» senza leggere gli header in risposta, in staging, con e senza cookie.

In sintesi

CORS è un header di risposta. Dice quale origin può leggere. Non chiude l’endpoint. Il jolly non sta con i cookie. Il preflight è un OPTIONS. null non si usa. Si verifica in console e sugli header, non sul lucchetto della home. MDN e la Fetch Standard, 20 settembre 2026.

Domande Frequenti

MDN: un meccanismo con cui il server, via header HTTP, dice al browser quale origin può leggere quella risposta. Serve a fetch(), XMLHttpRequest, font cross-origin, canvas, WebGL. Non autentica l'utente e non impedisce alla richiesta di arrivare al server.
No. MDN: con Access-Control-Allow-Credentials: true il jolly produce un errore. Si ecoa l'origin della richiesta e si aggiunge Vary: Origin, perché la cache non consegni a un secondo origin la risposta del primo.
Su metodi o header che non somigliano a un form HTML, il browser manda prima un OPTIONS con Access-Control-Request-Method e, se serve, Access-Control-Request-Headers. Il server risponde con Allow-Methods, Allow-Headers, eventualmente Max-Age. Poi parte la richiesta vera.
MDN: documenti data:, file: e iframe sandbox serializzano origin null. Molti browser concedono a quei documenti una risposta con Allow-Origin null, e un attaccante può costruire un documento ostile con origin null.
No. CORS non è un firewall. La richiesta arriva comunque. Il plugin che mette il jolly su ogni risposta apre la lettura a qualunque origin. Si impostano gli header sul server, si verificano in staging con e senza credenziali, si legge la console del browser.

Potrebbe interessarti anche...