> For the complete documentation index, see [llms.txt](https://simon-6.gitbook.io/simoncyber/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://simon-6.gitbook.io/simoncyber/portswigger-web-academy/xss/csp.md).

# CSP

### What is CSP (content security policy)? <a href="#what-is-csp-content-security-policy" id="what-is-csp-content-security-policy"></a>

CSP is a browser security mechanism that aims to mitigate XSS and some other attacks. It works by restricting the resources (such as scripts and images) that a page can load and restricting whether a page can be framed by other pages.

To enable CSP, a response needs to include an HTTP response header called `Content-Security-Policy` with a value containing the policy. The policy itself consists of one or more directives, separated by semicolons.

You can find CSP in either devtools or in the request headers of Burpsuite.&#x20;

<figure><img src="/files/UMeAvg0Nm1F3eEN9RV1D" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
**Any site with a CSP will show it in DevTools**, because CSP is delivered either as an HTTP response header or an HTML `<meta>` tag, both of which are fully visible client-side. There's no way for a site to hide its CSP from you — the browser itself needs to read it in order to enforce it, so it's always sitting right there in plain text.
{% endhint %}

<figure><img src="/files/9BTpj4phpCu96rYWp0Xf" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/SjOuA7oXlYppjFrkrCPP" alt=""><figcaption></figcaption></figure>

We put "test" in the URL and it is reflected back as HTML in our webpage. If we put something such as \<img src=1 onerror="alert(1)">

<figure><img src="/files/1cO9bsA5TqrZfTfWcY2i" alt=""><figcaption></figcaption></figure>

It works, but we see in the console it doesn't run the actual code.&#x20;

<figure><img src="/files/KDniZkBsz1atwrgqP1CL" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/OypeyAHVWdIkwzUUMRXV" alt=""><figcaption></figcaption></figure>

We see the CSP policy.&#x20;

Content-Security-Policy: default-src 'self'; object-src 'none';script-src 'self'; style-src 'self'; report-uri /csp-report?token=

#### 1. `default-src 'self';`

* What it means: This is the fallback rule (the "default" setting) for any type of resource that isn't explicitly defined later in the policy (such as images, fonts, AJAX requests, or audio/video).
* What `'self'` does: It tells the browser: *"Only load resources if they originate from the exact same domain, protocol, and port as this website."* If the site is `[https://example.com](https://example.com)`, it will block anything trying to load from `[https://evil-hacker.net](https://evil-hacker.net)` or even a subdomain like `[https://api.example.com](https://api.example.com)` (unless explicitly allowed).

#### 2. `object-src 'none';`

* What it means: This controls legacy plugins and embedded multimedia components via HTML tags like `<object>`, `<embed>`, or `<applet>` (traditionally used for things like Adobe Flash or Java Applets).
* What `'none'` does: It completely disables these tags. Because legacy plugins are notoriously prone to security vulnerabilities and can bypass normal browser execution rules, modern security practices dictate shutting them down entirely.

#### 3. `script-src 'self';`

* What it means: This defines the strict rules for JavaScript execution, which is the absolute core of XSS defense.
* Why it's highly restrictive: By setting this to `'self'`, the browser will only execute JavaScript files that are physically hosted on the website's own server.
* What it blocks:
  * It blocks scripts loaded from external servers (e.g., `<script src="[https://hacker.com/malicious.js](https://hacker.com/malicious.js)">`).
  * Crucially, it also blocks all inline JavaScript (e.g., `<script>alert(1)</script>` or HTML event attributes like `onclick="..."`). This single rule completely neutralizes traditional Reflected or Stored XSS payloads embedded directly inside an HTML response.

#### 4. `style-src 'self';`

* What it means: This restricts CSS stylesheets.
* What it does: Just like the script rule, it forces the browser to only load CSS files hosted directly on the website's own server. It prevents attackers from injecting external stylesheets or inline styles, which can sometimes be used maliciously to alter the UI layout, trick users into clicking buttons (clickjacking), or exfiltrate data via CSS selectors.

#### 5. `report-uri /csp-report?token=`

* What it means: This specifies a destination where the browser should automatically send a notification if any of the above rules are violated.
* How it works: If an attacker attempts an XSS attack by injecting an unauthorized script, the browser will block the script from running. Then, behind the scenes, it will automatically bundle up a JSON report detailing exactly what rule was violated, what resource triggered it, and send a `POST` request to `/csp-report?token=` so the website administrators can monitor and log the attempted attack.

However, there's one way we can bypass this. The injection uses the `script-src-elem` directive in CSP. This directive allows you to target just `script` elements. Using this directive, you can overwrite existing `script-src` rules enabling you to inject `unsafe-inline`, which allows you to use inline scripts.

| Directive         | Controls                                                                             |
| ----------------- | ------------------------------------------------------------------------------------ |
| `script-src`      | Everything script-related (fallback/general)                                         |
| `script-src-elem` | Only `<script>` **elements** specifically                                            |
| `script-src-attr` | Only inline event handler **attributes** (`onerror=`, `onclick=`, etc.) specifically |

{% hint style="info" %}
Because `script-src-elem` is more specific than `script-src` for the one thing it governs (`<script>` tags), CSP's precedence rules mean **if both are present, `script-src-elem` wins for `<script>` tags** — even overriding a stricter, pre-existing `script-src`
{% endhint %}

```
/?token=;script-src-elem 'unsafe-inline'&search=<script>alert(document.domain)</script>
```

#### Breaking down the `token` parameter

```
token=;script-src-elem 'unsafe-inline'
```

The semicolon (`;`) is the CSP **directive separator** — in a real CSP header, directives are chained like:

```
Content-Security-Policy: script-src 'nonce-xyz'; style-src 'self'; script-src-elem 'unsafe-inline'
```

After it, is our payload which works fine now.

\&search=alert(document.domain)
