KobReySec Logo
Published Last reviewed
CORS, In Plain English

CORS Explained

Cross-Origin Resource Sharing (CORS) is a browser security mechanism that controls when one website's JavaScript is allowed to read a response from another website.

If you landed here because a penetration test identified a CORS issue, this page is designed to explain what happened, why it matters, how to reproduce it, and where remediation usually starts.

Plain-English guide Interactive demos Remediation guidance
This page gets technical, because CORS gets technical. You do not need to understand every header to fix most CORS findings. Focus on who the application trusts, what data is exposed, and whether that access is actually required.
Start With the Human Version

Think of CORS Like a Receptionist Controlling Who Gets Information

Anyone may be able to knock on the office door and make a request. CORS is the browser asking whether the response is allowed to leave the office and be handed back to that particular visitor.

The Everyday Comparison

A website can often send a request to another website. The important CORS question is whether the browser lets the requesting site's JavaScript read the response.

The receptionist is the browser.The visitor can ask a question. The receptionist checks the office's policy before handing information back to that visitor.
Credentials are like bringing the user's room key.Allowing a stranger to ask a public question is very different from letting them ask while carrying the user's identity or session.

What Is an “Origin”?

An origin is basically a website's identity to the browser. It is made from the protocol, hostname, and port.

httpsProtocol
portal.example.comHostname
443Port
Together, those identify https://portal.example.com:443 as one origin.

Change any of those pieces and the browser may treat it as a different origin. That is why https://app.example.com and https://api.example.com are different origins even if the same company owns both.

01

Same Origin

app.exampleapp.example

JavaScript and the resource share an origin. The browser allows the response to be read normally.

Response readable
02

Cross-Origin, No Permission

kbry.netapp.example

The request may still reach the server, but the browser will not expose the response to the calling JavaScript.

Response blocked from script
03

Cross-Origin, Explicitly Allowed

kbry.netapp.example

The target explicitly permits the foreign origin. The browser may expose the response to that origin.

Response may be readable
The important distinction: a request being sent is not the same thing as JavaScript being allowed to read the response. CORS governs the second part.
The Moving Parts

The Concepts That Usually Cause the Confusion

You do not need to memorize the CORS specification. These are the pieces that explain most real-world findings.

What does “Credentials” mean?

In the browser Fetch API, credentials generally means cookies, HTTP authentication, and client certificates. When credentials are included, a server that wants JavaScript to read the response must explicitly allow the requesting origin and, where applicable, return Access-Control-Allow-Credentials: true.

A wildcard origin such as Access-Control-Allow-Origin: * cannot be used to expose a credentialed response to browser JavaScript. Our public authenticated demo deliberately uses a harmless custom header instead of cookies so the example does not create persistent browser state.

Did the request happen if the browser says it was blocked?

Often, yes. CORS primarily controls whether JavaScript can read a cross-origin response. A simple request may reach the target and be processed even when the browser later refuses to expose the response to the calling script.

This is why “blocked by CORS” does not mean “the server never received the request.” CORS is not a network firewall and it does not replace protections against Cross-Site Request Forgery (CSRF) or proper authorization.

Why does the Origin matter?

For cross-origin browser requests, the browser supplies an Origin header identifying where the calling JavaScript came from. The target can use that value to decide whether the origin should be trusted.

A common mistake is blindly copying that value into Access-Control-Allow-Origin. If any supplied origin is reflected back, an attacker-controlled site may receive the same permission as a legitimate application. This is one of the most common starting points for meaningful CORS findings.

What is a preflight request?

Think of a preflight like checking with security before entering a restricted area. The browser sends an OPTIONS request first and says, in effect: “I am from this origin, I want to use this method, and I want to send these headers. Is that allowed?”

If the server approves, the browser sends the actual request. Our authenticated API demo uses X-KRS-Demo-Auth, a custom request header, specifically so you can see this behavior.

What does a successful test actually prove?

A readable result proves that JavaScript running on our controlled https://kbry.net origin was able to read that response in the browser. It does not automatically mean the application is vulnerable.

The security impact depends on what the response contains, whether authentication is involved, whether the trusted origin can be controlled by an attacker, and whether the access is intentional.

Try a Controlled Example

See the Browser Rules in Action

These endpoints are hosted on cors-demo.kbry.net and intentionally configured to behave differently. Each one demonstrates a pattern commonly encountered during web application and API testing.

Expected: Readable

Public CORS

The endpoint returns Access-Control-Allow-Origin: *. It contains public data and intentionally allows any origin to read it.

Expected: Blocked

No CORS Permission

The server returns a normal HTTP response but sends no CORS permission. Browser JavaScript on kbry.net should not be able to read it.

Expected: Readable, Risky Pattern

Reflected Origin

The endpoint blindly reflects the supplied Origin. This is a common starting point for CORS findings because requester-controlled input is being turned into a trust decision.

Expected: Preflight + Readable

Authenticated API

The tester adds a harmless X-KRS-Demo-Auth header. The custom header causes a preflight and the API trusts only the controlled kbry.net origin.

These are intentionally configured lab endpoints. A readable demo result is expected behavior. They exist to make the browser security model visible before you test a real application.
Interactive Browser Test

Can a Foreign Origin Read the Response?

Enter an HTTPS URL you own or are authorized to assess. The browser test is initiated from https://kbry.net, a KobReySec-controlled foreign origin, and reports whether JavaScript on that origin can read the target response.

CORS Browser Proof of Concept

This is a browser-enforced test, not a server-side vulnerability scan.

Foreign-Origin Test
Only test systems you own or are authorized to assess. Browser privacy controls, authentication state, target behavior, and CORS policy all affect the result. The controlled authenticated demo uses a custom header and does not use browser cookies.

Browser Test ResultNo target tested
Origin: https://kbry.net
Foreign originhttps://kbry.net
RequestSimple GET
Browser credentialsNot tested
Response accessNot tested
Ready for a test

Enter a target URL or load a controlled example to see whether browser JavaScript running on the foreign origin can read the response.

Why the Browser Behaves Differently

Same Request. Different Context. Different Result.

CORS gets easier once you compare the cases side by side. The server response is only part of the story. The browser also considers the requesting origin, whether credentials are involved, and whether a preflight is required.

01

Wildcard vs. Explicit Origin

* + no credentialsReadable
* + credentialsBlocked

Access-Control-Allow-Origin: * is valid for many public responses, but a credentialed browser response must identify an allowed origin explicitly.

02

Browser vs. curl / Burp

Browser JavaScriptCORS enforced
curl / BurpResponse visible

CORS is enforced by browsers. Tools such as curl and Burp Suite can receive a response even when browser JavaScript would be prohibited from reading it.

03

Simple Request vs. Preflight

Simple GETRequest first
Custom headerOPTIONS first

A preflight lets the browser ask permission before certain cross-origin requests. If that permission check fails, the actual request may never be sent.

The “why” is the important part. A readable response, a blocked response, and a response visible in Burp can all be correct at the same time depending on who made the request and what the browser was asked to do.
If This Was in Your Report

Start With Trust, Then Reduce It to What Is Actually Required

Most CORS remediation is not about adding more headers. It is about making the trust decision narrower and more deliberate. The correct fix depends on why cross-origin browser access exists in the first place.

Common FindingArbitrary Origin Reflection

Do not copy the incoming Origin directly into Access-Control-Allow-Origin. Compare it against an exact allowlist of known, trusted application origins.

Common FindingWildcard Access on Sensitive Responses

Determine whether the resource truly needs to be readable by every website. If not, remove the wildcard and allow only the specific browser clients that require access.

Common FindingCredentialed Access to Untrusted Origins

Review both the allowed origin and Access-Control-Allow-Credentials. Sensitive authenticated responses should only be exposed to explicitly trusted origins.

Common FindingOverly Broad Methods or Headers

Allow only the HTTP methods and request headers the browser client actually needs. Avoid broad policies added simply to make errors disappear.

Common FindingBroad Subdomain Trust

If you trust patterns such as all company subdomains, verify that none of those subdomains can be claimed, delegated, uploaded to, or otherwise controlled by an attacker.

Always RequiredKeep Authorization Server-Side

CORS is not authorization. Every sensitive API response and action must still enforce authentication and authorization independently of the browser's CORS decision.

Risky PatternOrigin: https://attacker.exampleAccess-Control-Allow-Origin: https://attacker.example
Better PatternOrigin: https://portal.example.com↓ exact allowlist check ↓Access-Control-Allow-Origin: https://portal.example.com
A useful default: if an origin does not need to read the response from browser JavaScript, do not grant it CORS access. Grant the minimum cross-origin access the application actually requires.

Still Untangling a CORS Finding?

A readable response is not automatically a vulnerability, and a blocked response does not always mean the request failed. KobReySec performs hands-on web application and API penetration testing and can help determine whether the behavior has meaningful security impact.