Skip to content
1 change: 1 addition & 0 deletions astro.sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export const sidebar = [
'reference/experimental-flags/content-intellisense',
'reference/experimental-flags/preserve-scripts-order',
'reference/experimental-flags/heading-id-compat',
'reference/experimental-flags/csp',
],
}),
'reference/legacy-flags',
Expand Down
228 changes: 228 additions & 0 deletions src/content/docs/en/reference/experimental-flags/csp.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
---
title: Experimental Content Security Policy
sidebar:
label: Content Security Policy
i18nReady: true
---

import Since from '~/components/Since.astro'

<p>

**Type:** `boolean | Csp`<br />
**Default:** `false`<br />
<Since v="5.9.0" />
</p>

Enables support for [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) of the Astro built-in features.

```js title="astro.config.mjs"
import { defineConfig } from 'astro/config';

export default defineConfig({
experimental: {
csp: true
}
});
```

When enabled, Astro will add a `<meta>` element inside the `<head>` element of each page. The element will have the `http-equiv="content-security-policy"` attribute, and `content` attribute will change based on the script and styles used in the page.

```html
<head>
<meta
http-equiv="content-security-policy"
content="
script-src 'self' 'sha256-somehash';
style-src:'self' 'sha256-somehash'"
>
</head>
```

## Configuration

It's possible to customize the `<meta>` tag with the configuration.

### Default algorithm

Astro uses the `SHA-256` algorithm to generate the hashes of all the styles and scripts generated. It's possible to change it via configuration, and the variants supported are `SHA-256`, `SHA-512` and `SHA-384`:

```js title="astro.config.mjs"
import { defineConfig } from 'astro/config';

export default defineConfig({
experimental: {
csp: {
algorithm: 'SHA-512'
}
}
});
```

### Custom directives

While Astro needs to control the `script-src` and `style-src` directives, it's possible to control other directives using the `csp.diretives` field. These directives are added to all pages. It accepts a list of type-safe directives:

```js title="astro.config.mjs"
import { defineConfig } from 'astro/config';

export default defineConfig({
experimental: {
csp: {
directives: [
"default-src 'self'",
"image-src 'self' 'https://images.cdn.example.com'"
]
}
}
});
```

After the build, the `<meta>` element will look something like the following:

```html
<meta
http-equiv="content-security-policy"
content="
default-src 'self';
image-src 'self' 'https://images.cdn.example.com';
script-src 'self' 'sha256-somehash'; style-src:'self' 'sha256-somehash'
"
>
```

### Custom resources

As mentioned before, Astro needs to control the `script-src` and `style-src` directives, and by default it uses `'self'` resource, which means that scripts and styles can only be downloaded by the current host (usually the current website).

It's possible to **override** the resources via configuration. You can provide a list of resources, and Astro will use them instead of `'self'`. These resources are added to all pages:

```js title="astro.config.mjs"
import { defineConfig } from 'astro/config';

export default defineConfig({
experimental: {
csp: {
stylesDirective: {
resources: [
"self",
"https://styles.cdn.example.com"
]
},
scriptsDirective: {
resources: [
"https://cdn.example.com"
]
}
}
}
});
```

After the build, the `<meta>` element will look something like the following:

```html
<head>
<meta
http-equiv="content-security-policy"
content="
script-src 'https://cdn.example.com' 'sha256-somehash';
style-src: 'self' 'https://styles.cdn.example.com' 'sha256-somehash'"
>
</head>
```

### Custom hashes

If you have external scripts or styles that aren't generated by Astro, or some inline script, the configuration allows you to provide additional hashes to be rendered.

You must provide hashes that start with `sha384-`, `sha512-` or `sha256-`. Other values will cause a validation error. These hashes are added to all pages.


```js title="astro.config.mjs"
import { defineConfig } from 'astro/config';

export default defineConfig({
experimental: {
csp: {
stylesDirective: {
hashes: [
"sha384-styleHash",
"sha512-styleHash",
"sha256-styleHash"
]
},
scriptsDirective: {
hashes: [
"sha384-scriptHash",
"sha512-scriptHash",
"sha256-scriptHash"
]
}
}
}
});
```

After the build, the `<meta>` element will look something like the following:

```html
<meta
http-equiv="content-security-policy"
content="
script-src 'self' 'sha256-generatedByAstro' 'sha384-scriptHash' 'sha512-scriptHash' 'sha256-scriptHash';
style-src:'self' 'sha256-generatedByAstro' 'sha384-styleHash' 'sha512-styleHash' 'sha256-styleHash';
"
>
```

## Runtime APIs

Additionally, it's possible to customize the `<meta>` element, **per page**, via runtime APIs. The following APIs are available
from the `Astro` global inside `.astro` component, or the `APIContext` type.

### `addDirective`

<p>
**Type:** `(directive: CspDirective) => void`<br />
</p>

Adds a single directive to the current page. You can call this method multiple times, to add additional directives.

### `insertStyleResource`

<p>
**Type:** `(resource: string) => void`<br />
</p>

Insert a new resource to be used for the `style-src` directive.


### `addStyleHash`

<p>
**Type:** `(hash: CspHash) => void`<br />
</p>

Adds a new hash to the `style-src` directive.


### `insertScriptResource`

<p>
**Type:** `(resource: string) => void`<br />
</p>

Insert a new resource to be used for the `script-src` directive.

### `addScriptHash`

<p>
**Type:** `(hash: CspHash) => void`<br />
</p>
Adds a new hash to the `script-src` directive.


:::caution
Due to the nature of the vite dev server, this feature isn't supported in `dev`. It's recommended to test Astro application using `build` and `preview`
:::