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.
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.
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.
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.
An origin is basically a website's identity to the browser. It is made from the protocol, hostname, and port.
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.
JavaScript and the resource share an origin. The browser allows the response to be read normally.
The request may still reach the server, but the browser will not expose the response to the calling JavaScript.
The target explicitly permits the foreign origin. The browser may expose the response to that origin.
You do not need to memorize the CORS specification. These are the pieces that explain most real-world findings.
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.
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.
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.
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.
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.
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.
The endpoint returns Access-Control-Allow-Origin: *. It contains public data and intentionally allows any origin to read it.
The server returns a normal HTTP response but sends no CORS permission. Browser JavaScript on kbry.net should not be able to read it.
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.
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.
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.
This is a browser-enforced test, not a server-side vulnerability scan.
Enter a target URL or load a controlled example to see whether browser JavaScript running on the foreign origin can read the response.
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.
Access-Control-Allow-Origin: * is valid for many public responses, but a credentialed browser response must identify an allowed origin explicitly.
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.
A preflight lets the browser ask permission before certain cross-origin requests. If that permission check fails, the actual request may never be sent.
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.
Do not copy the incoming Origin directly into Access-Control-Allow-Origin. Compare it against an exact allowlist of known, trusted application origins.
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.
Review both the allowed origin and Access-Control-Allow-Credentials. Sensitive authenticated responses should only be exposed to explicitly trusted origins.
Allow only the HTTP methods and request headers the browser client actually needs. Avoid broad policies added simply to make errors disappear.
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.
CORS is not authorization. Every sensitive API response and action must still enforce authentication and authorization independently of the browser's CORS decision.
Origin: https://attacker.example↓Access-Control-Allow-Origin: https://attacker.exampleOrigin: https://portal.example.com↓ exact allowlist check ↓Access-Control-Allow-Origin: https://portal.example.comA 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.