A CORS allowlist is not authorization
A tight Access-Control-Allow-Origin list only controls which browsers may read a cross-origin response. It is not an authorization decision for who may act on which resource. Browsers enforce CORS. Scripts, mobile apps,
A tight Access-Control-Allow-Origin list only controls which browsers may read a cross-origin response. It is not an authorization decision for who may act on which resource.
Browsers enforce CORS. Scripts, mobile apps, curl, and server-to-server callers do not. If your API returns 200 for DELETE /invoices/inv_4821 whenever a valid session cookie or bearer token is present, a CORS allowlist never blocked that delete.
What usually goes wrong:
- Teams treat βnot allowed by CORSβ as βnot allowed for this user.β
- Object checks are skipped because βonly our SPA can call this API.β
- List endpoints return every tenantβs rows; the SPA hides what CORS would have blocked anyway.
Patterns that hold up:
- Authenticate the caller, then authorize each action on each resource id (ownership, role on that object, or an explicit grant).
- Filter list and search results by what the subject may see, on the server.
- Re-check on nested ids in batch and GraphQL paths.
Quick check: call the same mutating endpoint with a valid token from curl (no browser). If it succeeds for another userβs resource, CORS was never your authorization layer.
CORS is a browser reading rule. Object authorization belongs on the server.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.