Blog · E.21 · Technical

CORS misconfiguration explained

The browser's same-origin policy stops one site reading another's data. CORS deliberately relaxes that - and if you relax it too far, you hand an attacker's website the ability to read your logged-in users' data from your own application. The classic mistake is one line: reflect the Origin header and allow credentials. Here's what CORS actually does, the dangerous configurations, what an attacker steals, and how to lock it down.

CORSSame-Origin PolicyOrigin ReflectionCredentialsWeb AppSec
CORS: Relaxes Same-Origin Policy · Reflected Origin + Credentials = Trust Anyone · null Origin · Weak Regex · Cross-origin Data Theft · Fix = Strict Allow-list, Exact Match CORS: Relaxes Same-Origin Policy · Reflected Origin + Credentials = Trust Anyone · null Origin · Weak Regex · Cross-origin Data Theft · Fix = Strict Allow-list, Exact Match
// TL;DR

CORS relaxes the browser's same-origin policy to let your app share resources with specified origins. A misconfiguration relaxes it too far, letting an attacker's site read your logged-in users' data. The dangerous mistakes: reflecting the Origin header into Access-Control-Allow-Origin with Allow-Credentials: true (trusts everyone); trusting null; wildcard on sensitive data; and weak origin validation (substring/regex a lookalike domain satisfies). Impact: cross-origin theft of any logged-in user's data. Fix: treat CORS as access control - a strict allow-list with exact matching, credentials only for fully-trusted origins, never combined with a reflected or wildcard origin. Detail below - part of every web and API test.

// 01 What CORS actually does

By default, browsers enforce the same-origin policy: JavaScript on evil.com can send a request to yourapp.com, but it cannot read the response. That's a foundational protection - it's why a malicious site can't just read your webmail. CORS (Cross-Origin Resource Sharing) is the mechanism to deliberately relax that, so your legitimate front-end on one origin can call your API on another. The server signals which cross-origin sites are allowed to read responses using headers like Access-Control-Allow-Origin and, when cookies/credentials are involved, Access-Control-Allow-Credentials. The key mental shift: CORS is an access-control decision about who may read your responses. Get that decision wrong - trust the wrong origins - and you've re-opened exactly the hole the same-origin policy exists to close.

// 02 The dangerous configurations

01

Reflected origin + credentials

Echo the request's Origin into Allow-Origin and set Allow-Credentials: true - effectively trusting any origin with the user's session.

02

Trusting null

Allowing the null origin with credentials - suppliable from sandboxed iframes and some contexts.

03

Wildcard on sensitive data

Allow-Origin: * exposing authenticated or sensitive responses.

04

Weak validation

Substring/regex checks a lookalike domain satisfies - e.g. “ends with company.com” matched by company.com.evil.com.

The most common and most dangerous is the first: developers, wanting cross-origin calls to “just work,” reflect whatever Origin asks and enable credentials. That single pattern trusts every website on the internet with your users' authenticated sessions.

// 03 What the attacker gains

Here's the exploit, concretely. Your app trusts an attacker-controlled origin and allows credentials. A logged-in victim visits the attacker's page (a link, an ad, anything). The attacker's JavaScript makes a cross-origin request to your application - and because the browser includes the victim's cookies and your app allows the attacker's origin to read the response, the attacker's script reads the victim's authenticated data: personal details, API keys, tokens, account information - whatever those endpoints return. In some cases they can perform actions too. It's cross-origin data theft against any user who visits the attacker's page while logged in - no phishing of credentials needed, just a visit. That's why an exploitable CORS misconfiguration on an authenticated, sensitive endpoint is rated high severity, and why it's a recurring real-world finding, not a theoretical one.

// 04 How to test & configure it safely

Testing is quick and revealing: send requests with a crafted Origin header - an arbitrary attacker domain, null, and lookalike variants - and inspect the response headers. If the app reflects your arbitrary origin into Access-Control-Allow-Origin with Access-Control-Allow-Credentials: true, it's exploitable; if a lookalike domain is accepted, the validation is weak. It's a fast check that manual testers always run on APIs. Configuring safely: keep a strict allow-list of trusted origins and validate Origin against it with exact matching - never substring or loose regex; only return Allow-Origin for allow-listed origins; set Allow-Credentials: true only when genuinely required and the origin is fully trusted, and never combine credentials with a reflected or wildcard origin; don't trust null; and keep allowed methods/headers minimal. Treat it as the access-control decision it is - decide exactly which origins may read authenticated responses, and enforce it precisely. It's checked in every API and web engagement, per our methodology.

// 05 Frequently asked questions

What is a CORS misconfiguration?

CORS relaxes the browser's same-origin policy to let an app share resources with specified origins. A misconfiguration is an overly permissive or flawed policy letting an attacker's site make authenticated cross-origin requests to your app and read the responses. The most dangerous form reflects the Origin header into Access-Control-Allow-Origin while allowing credentials - effectively trusting any origin - so a malicious site can read a logged-in victim's data.

What are the most dangerous CORS mistakes?

Reflecting the arbitrary Origin into Allow-Origin with Allow-Credentials true (trusts every origin with credentials); trusting the null origin with credentials; wildcard where sensitive authenticated data is exposed; and weak origin validation like a substring or regex a lookalike domain satisfies. Each lets a malicious origin read authenticated responses it shouldn't.

What can an attacker do?

If the app trusts an attacker-controlled origin and allows credentials, a malicious site visited by a logged-in victim makes cross-origin requests in the victim's session and reads the responses - stealing personal details, API keys, tokens or account information, and sometimes performing actions. It's cross-origin data theft against any user who visits the attacker's page while logged in, hence high severity on sensitive endpoints.

How do you configure CORS securely?

Use a strict allow-list of trusted origins and validate Origin with exact matching, never substring or loose regex. Only return Allow-Origin for allow-listed origins, and only set Allow-Credentials true when genuinely required and the origin is fully trusted - never with a reflected or wildcard origin. Don't trust null. Keep methods and headers minimal. Treat CORS as an access-control decision.

// 06 Related reading

UG

Usama Gul

Founder & Penetration Testing Lead, CyberFortify

Runs the crafted-Origin check on every API — catching the reflected-origin-plus-credentials pattern that quietly trusts the whole internet with your users' sessions — and prescribes the exact-match allow-list fix.

Exposing an API?

One reflected-origin line can trust the whole internet with your users' sessions. We run the crafted-Origin check on every endpoint and hand you the exact-match allow-list fix.

Scope an API test → API testing →