Skip to content
IsSafeSite
2 min de lectureIsSafeSite Team

CORS expliqué : une configuration cross-origin sûre pour les sites modernes

CORS est aussi souvent mal compris que mal configuré. Voici ce que font réellement les en-têtes, le piège du joker avec identifiants, et comment verrouiller correctement une API.

CORSAPIDurcissement

Le partage de ressources entre origines (CORS) est souvent le premier contact d’une équipe avec la sécurité du navigateur — généralement parce que quelque chose a cassé et que le premier résultat de recherche disait « autorise simplement toutes les origines ». Ce correctif marche et devient en silence une vulnérabilité. Voici ce que CORS fait vraiment, et comment le configurer sans ouvrir votre API à tous les sites d’Internet.

Ce que CORS contrôle réellement

CORS n’est pas un contrôle d’accès côté serveur. C’est un mécanisme du navigateur qui décide si le JavaScript exécuté sur l’origine A a le droit de *lire* une réponse de l’origine B. Il ne fait rien pour arrêter une requête directe de curl, d’un serveur ou d’un script qui ignore le navigateur. Traitez-le comme un garde-fou pour clients navigateur et gardez quand même la vraie autorisation sur le serveur.

Le piège du joker avec identifiants

La configuration CORS la plus dangereuse consiste à renvoyer l’origine de la requête tout en autorisant les identifiants :

Access-Control-Allow-Origin: https://evil.example
Access-Control-Allow-Credentials: true

Si votre serveur renvoie tel quel n’importe quel Origin reçu et définit Allow-Credentials: true, n’importe quel site peut faire des requêtes authentifiées en tant que votre utilisateur connecté et lire la réponse. Le navigateur interdit le * littéral avec des identifiants pour cette raison — mais renvoyer l’origine contourne cette protection et recrée le trou.

Une configuration correcte et restrictive

Comparez l’origine entrante à une liste d’autorisation explicite et ne la renvoyez qu’alors :

const allowed = new Set([
  'https://app.example.com',
  'https://admin.example.com',
]);

const origin = req.headers.get('origin');
if (origin && allowed.has(origin)) {
  res.setHeader('Access-Control-Allow-Origin', origin);
  res.setHeader('Vary', 'Origin');
  res.setHeader('Access-Control-Allow-Credentials', 'true');
}

L’en-tête Vary: Origin est facile à oublier et important : sans lui, un cache peut servir l’en-tête d’autorisation d’une origine à une autre.

Restreignez aussi méthodes et en-têtes

Access-Control-Allow-Origin n’est que la moitié de la politique. Gardez le reste serré :

  • N’autorisez que les méthodes utilisées par le point d’accès, p. ex. Access-Control-Allow-Methods: GET, POST.
  • N’autorisez que les en-têtes de requête attendus, pas une liste globale.
  • Définissez un Access-Control-Max-Age raisonnable pour que les préflights soient mis en cache.
  • Ne combinez jamais Allow-Origin: * avec Allow-Credentials: true.

Quand un joker convient vraiment

Une API vraiment publique, sans authentification et en lecture seule — un flux de taux de change, un point d’état public — peut utiliser Access-Control-Allow-Origin: * en toute sécurité, précisément parce qu’il n’y a pas d’identifiants ni rien de privé à divulguer. Le danger ne vient que de l’ouverture type * combinée à l’authentification.

Testez depuis un vrai contexte cross-origin

CORS se comporte différemment pour les requêtes simples et celles avec préflight ; testez donc les deux depuis un navigateur sur une autre origine, pas seulement avec curl (qui ignore totalement CORS). Une analyse vérifie automatiquement vos en-têtes de réponse CORS avec le reste de vos vérifications de sécurité ; pour voir comment les constats CORS s’intègrent à une liste de correctifs priorisée, lisez Comment lire un rapport d’analyse de sécurité de site web.

Transformez ces vérifications en un rapport d’analyse pour votre propre site.

Lancez une analyse gratuite et obtenez des constats priorisés et exploitables en environ 30 secondes.

Analyser mon site

À lire ensuite