RSTR-NET-003 — Wildcard CORS with credentials, or bare wildcard ACAO
Summary
Two adjacent misconfigurations:
-
Wildcard origin + credentials.
cors({ origin: '*', credentials: true })(or the manual-header form) — browsers reject the combination, and if the code later "fixes" it by reflectingOrigin, every site on the internet gets credentialed cross-origin access. -
Bare
Access-Control-Allow-Origin: *on an endpoint that returns sensitive data — even without credentials, the endpoint is exposing JSON cross-origin to anyone.
The second case is Medium severity (intent ambiguous), the first is
High.
Languages
JavaScript, TypeScript.
What rastray flags
app.use(cors({ origin: '*', credentials: true })); // ← flagged
app.use(cors({ origin: true, credentials: true })); // ← flagged
res.setHeader('Access-Control-Allow-Origin', '*'); // ← flagged (Medium)
What rastray deliberately does not flag
cors({ origin: ['https://app.example.com'] }).- Static
Access-Control-Allow-Origin: https://app.example.com.
How to fix it
Allow-list specific origins; never combine wildcard with credentials:
const ALLOWED = ['https://app.example.com', 'https://admin.example.com'];
app.use(cors({
origin: (origin, cb) => {
if (!origin || ALLOWED.includes(origin)) return cb(null, true);
cb(new Error('not allowed'));
},
credentials: true,
}));
For a truly public API that returns only non-sensitive data,
cors({ origin: '*' }) (no credentials) is fine — see
RSTR-CORS-002 for the same vulnerability via
the manual-header form.