# CORS (Cross Origin Resource Sharing)

* Cross-origin resource sharing (CORS) is a **browser mechanism which enables controlled access to resources located outside of a given domain.**<br>

* It **extends and adds flexibility to the same-origin policy (SOP)**. However, it also provides potential for cross-domain attacks, if a website's CORS policy is poorly configured and implemented.

* **CORS is not a protection** **against** cross-origin attacks such as cross-site request forgery **(CSRF)**

* The cross-origin resource sharing protocol uses a suite of HTTP headers that define trusted web origins and associated properties such as whether authenticated access is permitted. These are combined in a header exchange between a **browser and the cross-origin web site that it is trying to access**.

## CORS and the Access-Control-Allow-Origin response header

The [cross-origin resource sharing](https://portswigger.net/web-security/cors) specification provides controlled relaxation of the [same-origin policy](https://portswigger.net/web-security/cors/same-origin-policy) for HTTP requests to one website domain from another through the use of a collection of HTTP headers. \
Browsers permit access to responses to cross-origin requests based upon these header instructions.\
\
CORS specification prescribes header exchanged between web server of requested domain  and browser that restricts origin for web resources request outside of the origin domain.\ <br>

```
Request Send by Browser:

GET /data HTTP/1.1
Host: robust-website.com
Origin : https://normal-website.com
```

```
Response RECIVED from website:

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.com
```

Browser will allow code running(Javascript) on `normal-website.com` to access the response because the origins match.\ <br>

### Handling cross-origin resource requests with credentials<br>

Default behavior of cross-origin resource requests is for requests to be passed without credentials like cookies and the Authorization header.&#x20;

{% content-ref url="/pages/qPY3UdMemte1QUfkxGgw" %}
[SOP (Same Origin Policy)](/sec-book/web-vulnerabilities/client-side-vulnerabilties/sop-same-origin-policy.md)
{% endcontent-ref %}

The cross-domain server can permit reading of the response when credentials are passed to it by setting the CORS `Access-Control-Allow-Credentials` header to true.

```
GET /data HTTP/1.1
Host: robust-website.com
...
Origin: https://normal-website.com
Cookie: JSESSIONID=<value>
```

```
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Credentials: true


```

#### Step by Step process:

{% stepper %}
{% step %}

#### Sending Cross Origin Request

JS makes a request with `credentials: "include"` → Browser immediately attaches cookies for the request domain (unless blocked by `SameSite`).
{% endstep %}

{% step %}

#### Attached Cookies

Request goes to the server with cookies.
{% endstep %}

{% step %}

#### Cookies Processing

Server processes cookies (e.g., authenticates session) and returns a response with CORS headers.
{% endstep %}

{% step %}

#### Response

If `Access-Control-Allow-Credentials: true` **AND** `Access-Control-Allow-Origin` is **not `*`**, then the browser allows JS to access the response body.\
\
If these headers are missing or wrong, the response is received at network level, but your JS cannot access its body or headers — you get a CORS error.
{% endstep %}
{% endstepper %}

#### Secenario 1:  Make a **cross-origin request** with credentials but did not received \`Access-Control-Allow-Credentials: true\` :

```
//Response only contain this header 

Access-Control-Allow-Origin: https://your-frontend.com
```

* Cookies are sent.
* Server sees them, uses them (e.g., for session/auth).
* &#x20;**Response:** Browser receives it at network level, but Browser blocks your JavaScript from seeing the response body and most headers because the CORS policy says:\
  “If credentials are involved, the response must have `Access-Control-Allow-Credentials: true`. Otherwise, reject it.”

#### Secenario 2:  Make a **cross-origin request** without credentials, where it is required:

```
HTTP/1.1 401 Unauthorized

Access-Control-Allow-Origin: https://your-frontend.com
Access-Control-Allow-Credentials: true (MAY BE)
```

* Browser sends request: **no cookies attached**
* Server receives request **without the cookie it expects**
* &#x20; Server checks auth: **no cookie → user not authenticated**
* Server responds — usually with an error like **401 Unauthorized** or **403 Forbidden** (depends on backend logic)<br>

### Pre-flight Checks:&#x20;

A **pre-flight** is an automatic `OPTIONS` request the browser sends **before** your actual `fetch` or `XHR` call **to ask the server for permission**.

The browser does this when it thinks the actual request *might be risky* by CORS rules.

```
OPTIONS /data HTTP/1.1
Host: <some website>
...
Origin: https://normal-website.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Special-Request-Header
```

```
HTTP/1.1 204 No Content
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240
```

### When does a preflight happen?

A preflight is sent if your request is **NOT a “simple request.”**

### Requirements for a Simple Request:

#### Method:

```
GET
HEAD
POST
```

#### Allowed Headers:

```
Accept
Accept-Language
Content-Language
Content-Type (but with restrictions, see below)
DPR
Downlink
Save-Data
Viewport-Width
Width


No other headers allowed.
Custom headers like Authorization or X-API-Key will trigger a preflight.
```

#### Content-Type Restrictions:

If you use the `Content-Type` header, its value must be **one of these three MIME types exactly:**

* application/x-www-form-urlencoded
* multipart/form-data
* text/plain

Any other `Content-Type` — for example, `application/json` — is **not safelisted** and triggers a preflight.

#### Upload body:

If the request has a body, it must be allowed for the chosen method.\
For `GET` and `HEAD`:

* No request body allowed (standard HTTP rule).

For `POST`:

* Body allowed — but must match allowed `Content-Type`.

| Request                                                                              | Simple? | Reason                                     |
| ------------------------------------------------------------------------------------ | ------- | ------------------------------------------ |
| `fetch('/api')`                                                                      | ✅       | `GET` with default headers                 |
| `fetch('/api', { method: 'POST', headers: { 'Content-Type': 'text/plain' } })`       | ✅       | Allowed method + allowed `Content-Type`    |
| `fetch('/api', { method: 'POST', headers: { 'Content-Type': 'application/json' } })` | ❌       | `application/json` is not safelisted       |
| `fetch('/api', { method: 'PUT' })`                                                   | ❌       | `PUT` is not an allowed method             |
| `fetch('/api', { headers: { 'Authorization': 'Bearer xyz' } })`                      | ❌       | `Authorization` is not a safelisted header |

### References:

* &#x20;<https://web.dev/articles/cross-origin-resource-sharing>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://n0m4dsec.gitbook.io/sec-book/web-vulnerabilities/client-side-vulnerabilties/cors-cross-origin-resource-sharing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
