Developers don't understand CORS (2019)

Many web developers remain confused about Cross-Origin Resource Sharing (CORS), a browser mechanism that relaxes the Same Origin Policy to let sites opt in to sharing data with other origins while trying to protect users from cross-site attacks. Commenters highlight that CORS is enforced only by compliant browsers, often feels backwards because it protects the user rather than the server, and is easy to misconfigure, leading to insecure “allow *” setups or brittle workarounds. Several argue that the real security boundary is the Same Origin Policy and CSRF protections, while CORS is a nuanced, poorly explained exception layer whose complexity is amplified by weak tooling and infrequent use.

Overall sentiment

  • Many participants admit they don’t really understand CORS, even experienced web devs.
  • The comment thread itself is cited as evidence that the ecosystem is deeply confused about CORS and its threat model.

Same-Origin Policy vs CORS

  • Several comments stress that the core security mechanism is the Same-Origin Policy (SOP); CORS is a way to selectively relax it.
  • Key clarification: the browser normally blocks reading cross-origin responses, not sending requests; CORS allows some cross-origin reads when the server opts in.

Threat model and what CORS actually protects

  • CORS is described as protecting the user in a browser from malicious third-party sites, not protecting the backend from generic HTTP clients.
  • Typical scenario: user is logged into site A (cookies set), then visits malicious site B that tries to read private data or act on their behalf against A.
  • Several comments note overlap and confusion with CSRF protections; some conflate the two, others insist CSRF must still be handled separately.

Preflight, “simple” requests, and edge cases

  • Many CORS pitfalls stem from the distinction between:
    • “Simple” requests (GET, some POSTs with specific content types) that bypass preflight.
    • “Non-simple” requests (e.g., JSON POST, custom headers) that require an OPTIONS preflight and explicit CORS approval.
  • Examples show how lax Content-Type checking (e.g., accepting JSON in text/plain or form encodings) can bypass preflight-based assumptions.
  • Commenters emphasize that potentially destructive behavior must not be exposed via “safe” or simple methods like GET.

Misuse and misconceptions

  • Common pattern: developers “just set Access-Control-Allow-Origin: *” to make things work, ignoring security implications.
  • Some wrongly believe CORS can prevent other sites or scrapers from calling an API at all; others correct that non-browser or CORS-disabled clients are unaffected.
  • The Zoom localhost example is called misleading: CORS headers would not have fully “restricted” access as implied.

Developer experience and learning

  • Debugging is described as painful: browser error messages are opaque, devtools views are confusing, and the real cause (server headers) is hidden.
  • Many see CORS as “set-and-forget”; they relearn it each time, then forget.
  • Some recommend MDN’s CORS docs and understanding SOP first; others argue the spec and docs are too complex and thus the protocol is effectively “bad.”

Architecture and alternatives

  • One view: best is to host frontend and backend on the same origin (via reverse proxy) and avoid CORS entirely.
  • Counterpoint: real-world architectures often require separate origins, so understanding and configuring CORS remains necessary.