Vulnerabilities
CORS Credentials vs Wildcard Origins
September 22, 2022
CORS credentials vs wildcard origins is a combination the Fetch spec forbids. If Access-Control-Allow-Credentials is true, Access-Control-Allow-Origin must be an explicit origin, not *. Reflecting any Origin while setting credentials true is the 'dynamic *' miss — you named one origin per response but allowed every caller. Public APIs that do not use cookies should omit credentials and may use * only when the body is meant for the whole web. Cookie or Authorization-header APIs need a strict allowlist. RoastMyOpsec app mode sends a bounded untrusted Origin and reads ACAO / credentials behavior. It does not send your users' cookies or attempt account takeover.
The practical difference
Credentials mode is whether the browser will attach cookies (and some client certs) on the cross-origin call. Wildcard ACAO is 'anyone may read this.' Together they would mean anyone may read cookie-authenticated JSON — so browsers refuse. Operators who still want 'open CORS plus cookies' often echo Origin. That is not a wildcard in the header string, but it is a wildcard in spirit.
See CORS wildcard vs allowlist for the public-JSON case, and CORP vs CORS for embedding locks.
How to choose based on the API
Anonymous public JSON: ACAO * , no Allow-Credentials. SPA on https://app.example.com calling https://api.example.com with cookies: ACAO https://app.example.com, Allow-Credentials true, SameSite on those cookies, CSRF still in play for cookie sessions. Do not allow https://evil.example by reflecting Origin.
| Pattern | Browser accepts? | Who can read with cookies? | Takeaway |
|---|---|---|---|
| ACAO * + credentials true | No | Nobody (failed CORS) | Broken and loud |
| ACAO * + credentials absent | Yes for credentialless | N/A — cookies not sent | OK for truly public bodies |
| Named origin + credentials true | Yes | That origin's pages | Default for cookie APIs |
| Echo any Origin + credentials true | Yes, per request | Whoever called | Treat as wildcard; don't |
What the roast can see
A hostile Origin and the ACAO / credentials headers on that response. Echoing our test Origin with credentials is a signal. It is not a stolen session. Pair with SameSite and CSRF guides for cookie APIs.
Common mistakes
The first mistake is * plus credentials because a framework defaulted both.
The second mistake is reflecting Origin with a regex that allows any https subdomain.
The third mistake is Access-Control-Allow-Headers: * with credentials without knowing which headers you meant.
Free audit the URL you own
RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.
Free audit nowFAQ
- Why did my CORS request fail with * and credentials?
- Browsers reject that pair. Use a specific origin or drop credentials.
- Is echoing Origin with credentials a vulnerability?
- It is an allow-everyone policy. If the API is authenticated with cookies, that is a serious miss. Allowlist the SPA origin.
- Does RoastMyOpsec use my session cookie in CORS tests?
- No. Bounded Origin header only. No account takeover, no credential stuffing.