CORS misconfiguration: how it works, how to detect it, how to fix it

Overly permissive CORS - a reflected Origin with credentials, a wildcard, or an allowed null origin - lets malicious sites read authenticated responses.

Typical severity: High · Checked by NovaPentest module: CORS

What it is

Cross-Origin Resource Sharing (CORS) is the browser mechanism that relaxes the Same-Origin Policy so a page on one origin can read responses from another. The server controls this with response headers - chiefly Access-Control-Allow-Origin (ACAO), which names the origin allowed to read the response, and Access-Control-Allow-Credentials (ACAC), which when set to true lets the cross-origin request carry cookies and authorization.

A misconfiguration is any policy that trusts origins it should not. The most dangerous pattern is reflecting the caller's Origin header back in ACAO while also sending ACAC: true - effectively "any site may read this authenticated response." Because the request carries the victim's cookies, a malicious page can read data as the victim. A blanket wildcard (ACAO: *) is less severe because browsers refuse to send credentials with it, but it still exposes any non-authenticated but sensitive API. Accepting the special value "null" is also unsafe: the null origin is produced by sandboxed iframes, data: documents, and local files, so an attacker can easily present it. Weak allowlist logic - matching a substring, or a trusted domain as a prefix or suffix, or trusting subdomains that can be taken over - falls in the same family.

CORS controls what scripts may read, not whether the request reaches the server, so it is fundamentally a confidentiality control. These issues map to OWASP Broken Access Control / Security Misconfiguration and CWE-942 (overly permissive cross-domain policy).

How it is exploited

CORS misconfigurations are exploited from the victim's browser. An attacker lures an authenticated user to a page they control; that page runs JavaScript that makes a cross-origin fetch to the vulnerable API with credentials included. If the server reflects the attacker page's origin into Access-Control-Allow-Origin and returns Access-Control-Allow-Credentials: true, the browser lets the attacker's script read the response - which was generated using the victim's session cookies.

The script then exfiltrates whatever the endpoint returns: profile data, API keys, CSRF tokens, account details, or anything the victim is authorized to see. Reading a CSRF token this way can chain into state-changing requests, escalating a read primitive toward account takeover. The null-origin variant works the same way but is triggered from a sandboxed iframe or a local document that presents Origin: null, useful when the server special-cases null.

A plain wildcard (ACAO: *) cannot be combined with credentials by the browser, so it does not expose cookie-authenticated data; its risk is limited to endpoints that return sensitive information without relying on cookies, or that authenticate via a bearer token the attacker's page can supply. No server exploit is required - the browser willingly hands over the response because the server told it the origin was trusted. Impact ranges from sensitive-data disclosure to full account takeover when tokens or CSRF secrets are exposed.

How to detect it

NovaPentest's CORS module tests the target with crafted Origin headers and reads the response's CORS headers. First it sends a GET with an arbitrary attacker origin (https://evil-pentgen-test.com) and inspects Access-Control-Allow-Origin and Access-Control-Allow-Credentials. If ACAO is exactly "*", it reports a wildcard origin at Medium. If instead the server reflects the exact evil origin back, it reports arbitrary-origin reflection - High on its own, and Critical when Access-Control-Allow-Credentials is also true, because reflected origin plus credentials is the account-takeover pattern.

It then sends a second GET with Origin: null; if the server answers with Access-Control-Allow-Origin: null, it reports that the null origin is allowed at High. The module reasons only about these response headers, so it detects reflection, wildcard, and null-origin trust rather than every possible allowlist bypass.

To verify manually, run `curl -sI -H "Origin: https://evil.example" https://api.target.com/endpoint` and look at the returned Access-Control-Allow-Origin and Access-Control-Allow-Credentials; repeat with `-H "Origin: null"`. A response echoing your arbitrary origin - especially alongside Allow-Credentials: true - confirms the flaw. Also probe near-miss origins (a trusted domain with an added prefix or suffix, or a look-alike) to expose sloppy allowlist matching the automated check does not attempt.

How to fix it

1. Use an explicit allowlist. Compare the incoming Origin against a fixed set of exact, trusted origins (full scheme + host + port) and only then echo that same value into Access-Control-Allow-Origin. Never blindly reflect the Origin header.

2. Never pair reflection or wildcards with credentials. If Access-Control-Allow-Credentials: true is required, ACAO must be a single specific origin - never "*", never a dynamically reflected arbitrary value.

3. Reject the null origin. Do not include "null" in the allowlist; treat requests presenting Origin: null as untrusted.

4. Match origins exactly. Avoid substring, prefix, or suffix checks and regexes that can be fooled (for example "example.com.attacker.com" or "attacker-example.com"); anchor the comparison to the whole origin string.

5. Scope narrowly. Apply CORS only to endpoints that genuinely need cross-origin access, keep wildcards off any endpoint that returns sensitive or authenticated data, and limit Access-Control-Allow-Methods and -Headers to what is needed.

6. Do not rely on CORS for authorization. It governs what browsers may read, not who may call the API; keep server-side access control and CSRF defenses in place regardless.

7. Watch subdomains. If your allowlist trusts subdomains, ensure none are vulnerable to takeover, or a claimed subdomain becomes a trusted origin.

Prioritize reflected-origin-with-credentials (Critical) first, then null-origin and plain reflection, then wildcards on sensitive endpoints.

Check your own site

Start with the free passive scan: no account needed, and you get an A to F grade covering headers, TLS, cookies, DNS and other configuration a visitor can observe. It does not send attack payloads, so it will not confirm every class of flaw. The full scan, available with a free account, runs the active checks, including the one described on this page.

Scan your site free