Limites CORS : en-tetes, preflight, identifiants et cache
Diagnostiquer les requetes cross-origin sans confondre CORS avec le reseau, la CSP, Permissions Policy ou l autorisation serveur.
BotBrowser Team
Vous voulez la documentation structurée pour Plateforme ?
Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.
let pageOrigin = '';
let apiOrigin = '';
const observations = [];
const listen = server => new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
const close = server => new Promise(resolve => server.close(resolve));
const api = http.createServer((request, response) => {
const name = request.url.slice(1);
if (name === 'control') response.setHeader('Access-Control-Allow-Origin', pageOrigin);
observations.push({ name, status: 200, allowOrigin: response.getHeader('Access-Control-Allow-Origin') || null });
response.writeHead(200, { 'Content-Type': 'application/json' });
response.end('{"fixture":true}');
});
const pageServer = http.createServer((request, response) => {
const name = request.url.slice(1);
response.end(<button>Run CORS check</button><output data-testid="cors-status"></output><script> document.querySelector('button').onclick = async () => { try { await fetch('${apiOrigin}/${name}'); document.querySelector('output').textContent = 'CORS_ALLOWED'; } catch { document.querySelector('output').textContent = 'FETCH_UNCLASSIFIED'; } };</script>);
});
await listen(api); await listen(pageServer);
const apiPort = api.address().port; const pagePort = pageServer.address().port;
pageOrigin = http://127.0.0.1:${pagePort};
apiOrigin = http://127.0.0.1:${apiPort};
const browser = await chromium.launch();
const context = await browser.newContext();
context.setDefaultNavigationTimeout(8_000);
async function runCase(name) {
const page = await context.newPage();
try {
await page.goto(${pageOrigin}/${name});
await page.getByRole('button', { name: 'Run CORS check' }).click();
await page.locator('[data-testid="cors-status"]').waitFor({ state: 'visible', timeout: 5_000 });
return await page.locator('[data-testid="cors-status"]').textContent();
} catch { return 'UNKNOWN'; }
finally { await page.close(); }
}
try {
const control = await runCase('control');
const candidate = await runCase('candidate');
assert.equal(control, 'CORS_ALLOWED');
assert.equal(candidate, 'FETCH_UNCLASSIFIED');
assert.deepEqual(observations.map(({ name, allowOrigin }) => ({ name, allowOrigin })), [
{ name: 'control', allowOrigin: pageOrigin }, { name: 'candidate', allowOrigin: null }
]);
} finally { await context.close(); await browser.close(); await close(pageServer); await close(api); }
Control doit afficher `CORS_ALLOWED` apres lecture du corps synthetique. Candidate affiche `FETCH_UNCLASSIFIED` apres le rejet Fetch; cet etat seul ne prouve pas CORS. Confirme `CORS_BLOCKED` seulement si le journal de l API possedee montre que les deux routes ont atteint l API et renvoye le meme corps avec 200, que candidate omet Allow-Origin, et que control a lu la reponse avec l origine exacte de la page.
Une erreur de navigation, statut ou serveur reste `UNKNOWN`; elle ne doit pas etre attribuee au reseau ni a CORS. La navigation est limitee a huit secondes et chaque page est fermee dans cleanup.
## Tableau de diagnostic
| Observation | Proprietaire initial | Verification | Conclusion prudente |
| ---------------------------------- | -------------------- | ------------------------------------- | ----------------------------------- |
| DNS, TLS ou connexion echoue | Reseau | Route, proxy, service | Aucune reponse CORS |
| Preflight 4xx/5xx | API | Route OPTIONS et en-tetes | Echange prealable echoue |
| 200 mais corps illisible | API/navigateur | Origin, identifiants, headers exposes | Partage refuse ou opaque |
| Cookie absent | Auth/navigateur | mode d identifiants, SameSite, Secure | CORS ne rend pas le cookie eligible |
| Origines avec resultats differents | API/cache | Liste et `Vary: Origin` | Politique ou cache differents |
| Violation CSP | Securite web | `connect-src`, rapports | Blocage CSP |
Ce que BotBrowser etablit
Les BrowserContexts controles de BotBrowser peuvent executer des fixtures CORS autorises et possedes, isoler cookies et stockage synthetiques et comparer des resultats Fetch visibles sur un build declare. La [documentation d isolation multi-compte](https://botbrowser.io/docs/identity/multi-account-isolation/) explique cette limite.
Pour valider CORS, BotBrowser peut executer la comparaison control/candidate, mais ne peut pas configurer la reponse API ni contourner la regle de partage du navigateur.
BotBrowser ne redige ni ne deploie les en-tetes CORS, n accorde pas l autorisation serveur, ne repare pas une API tierce, ne change pas l origine et ne contourne pas l enforcement du navigateur. Il ne prouve pas non plus l achevement d une operation distante. Ces faits restent ceux du serveur, du CDN et de l application.
Checklist
1. Declare les deux origines, methode, en-tetes, mode d identifiants et resultat attendu.
2. Verifie reseau et route avant une erreur de politique.
3. Capture Origin, preflight, statut, en-tetes, `Vary` et cache.
4. Separe CORS, CSP, Permissions Policy, permission utilisateur et autorisation.
5. Utilise huit secondes pour la navigation et cinq pour le statut, puis nettoie.
6. Conserve les types reseau, timeout, preflight et CORS distincts.
**Auteur :** BotBrowser Team
Voir le [guide d isolation cross-origin](/fr/blog/cross-origin-isolation-and-shared-memory-requirements/) et le [guide Permissions Policy](/fr/blog/permissions-policy-for-embedded-browser-features/).
## Sources
- Fixture URL (example only): https://app.example.test`
- Fixture URL (example only): https://app.example.test/control`
- [Protocole CORS Fetch](https://fetch.spec.whatwg.org/#http-cors-protocol)
- [CORS sur MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
- [CSP sur MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)
- [Permissions Policy sur MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Permissions_Policy)
Articles Connexes
Faites passer BotBrowser de la recherche à la production
Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.