RoastMyOpsec

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.

PatternBrowser accepts?Who can read with cookies?Takeaway
ACAO * + credentials trueNoNobody (failed CORS)Broken and loud
ACAO * + credentials absentYes for credentiallessN/A — cookies not sentOK for truly public bodies
Named origin + credentials trueYesThat origin's pagesDefault for cookie APIs
Echo any Origin + credentials trueYes, per requestWhoever calledTreat 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 now

FAQ

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.

Sources

Related guides