CodePark/ questions / CORS
START PRACTICINGPRACTICE
Backend question · HTTP & API design › CORS

This NestJS-style CORS setup reflects any origin back with credentials. What is wrong with it, and how would you fix it?

app.enableCors({
  origin: (origin, cb) => cb(null, origin),
  credentials: true,
});

The problem: it sends back every Origin together with Access-Control-Allow-Credentials: true. This is the same as allowing * with credentials, which the spec forbids for good reason. Any site that a logged-in user visits can call the API with the user's cookies and read the responses. So another site can read private data.

The fix is an explicit allowlist. Compare the incoming origin with exact strings like https://app.shop.com. Echo it back only if it matches.

Avoid these mistakes:

  • Loose checks like endsWith("shop.com"). They also match evilshop.com.
  • Allowing the null origin. Sandboxed iframes and some redirects send null.

When the allowed origin changes per request, send Vary: Origin. This stops caches from serving one origin's CORS headers to another origin. Setting Access-Control-Max-Age reduces repeated preflights. A preflight is the OPTIONS request the browser sends before some cross-origin requests.

  • Sending back any origin with credentials exposes user data to other sites.
  • Use an exact allowlist of origins.
  • Avoid suffix or regex mistakes, and don't allow the null origin.
  • Send Vary: Origin when the allowed origin changes per request.