Guide27 July 2026

Access-Control-Allow-Origin: * Feels Like a Convenience. It's Usually a Vulnerability.

Access-Control-Allow-Origin: * Feels Like a Convenience. It's Usually a Vulnerability.

Access-Control-Allow-Origin: * Feels Like a Convenience. It's Usually a Vulnerability.

Every developer has hit a CORS error at some point, a request that works fine from Postman but fails silently in the browser console with a message about Access-Control-Allow-Origin. It's one of the most common sources of "works on my machine" frustration in web development, and it has a one-line fix that a lot of teams reach for without thinking too hard about what it actually does: Access-Control-Allow-Origin: *.

What CORS is actually protecting

Cross-Origin Resource Sharing exists because of a much older browser protection called the Same-Origin Policy, which by default stops JavaScript running on one website from making requests to a different website using the visitor's existing session or cookies. Without that protection, any malicious site you happened to visit could quietly fire requests at your bank, your email provider, or any other site you were logged into, using your own active session, and read the responses.

CORS headers are how a server explicitly opts back into allowing specific cross-origin requests, for legitimate cases like a frontend hosted on one domain talking to an API hosted on another. The header tells the browser exactly which origins are allowed to make that request and read the response back.

What the wildcard actually does

Access-Control-Allow-Origin: * tells the browser that literally any website is allowed to read the response from this endpoint. Combined with an endpoint that returns anything user-specific, profile data, account details, internal records, this means any site on the internet can make a request to your API from a visitor's browser and read back whatever that visitor is authorized to see.

The nuance that catches people out: a wildcard alone doesn't send cookies along with the request, browsers block that combination by design. But a lot of misconfigurations pair a wildcard-like open policy with Access-Control-Allow-Credentials: true, or worse, dynamically reflect whatever Origin header the request sent back as the allowed origin, which achieves the same effect as a wildcard while looking more deliberate. That combination does allow cookies, and it's the one that actually matters.

A realistic exploit path

  1. An API endpoint reflects any request's Origin header back in Access-Control-Allow-Origin, effectively acting as a wildcard while looking configured
  2. Access-Control-Allow-Credentials: true is also set, so the browser will include the visitor's session cookies
  3. An attacker hosts a page anywhere, evil-site.com, with a script that quietly calls your API's /account/details or similar endpoint
  4. A logged-in visitor to that page, who never interacted with your site directly in that session, has their browser silently include their real session cookie
  5. The response, containing whatever that endpoint returns for the logged-in user, gets read by the attacker's script and exfiltrated

No password needed. No phishing needed beyond getting someone to load a page. The victim's own browser and their own valid session do all the work.

Why teams end up here

Almost nobody sets a wildcard CORS policy maliciously. It's nearly always a development-speed decision: the frontend and backend are on different ports or subdomains during local development, CORS errors block every request, and the fastest fix is opening the policy wide rather than configuring it properly. It works, the error disappears, and the same configuration often ships to production because revisiting it isn't anyone's priority once things are working.

How to check your own API

Open DevTools → Network on a request to your API, and look at the response headers. If you see Access-Control-Allow-Origin: *, or an origin value that exactly matches whatever request you just sent from an unrelated domain (a sign it's being reflected dynamically rather than checked against an allowlist), that's worth investigating. Check specifically whether Access-Control-Allow-Credentials: true is present alongside it, that's the combination that turns an open policy into an exploitable one.

How to fix it

  1. Maintain an explicit allowlist of origins that are actually allowed to call your API, your own frontend domains, known partner integrations, nothing else.
  2. Never combine a wildcard or reflected origin with Allow-Credentials: true. If an endpoint needs credentials, it needs a real allowlist, no exceptions.
  3. Scope permissive policies to endpoints that genuinely need them. A public, read-only endpoint with no user-specific data is a reasonable candidate for a wildcard. Anything behind authentication is not.
  4. Re-check this whenever you add a new frontend or partner integration. Allowlists drift out of date the same way subdomains do, quietly, until nobody remembers what's actually on the list or why.

Decloak checks your CORS configuration alongside seven other attack surfaces, HTTP headers, exposed secrets, session cookies and more, in a free 15-second scan. Scan your site free →