diff --git a/astro.sidebar.ts b/astro.sidebar.ts index d494e32dc76e9..6c167dfce705b 100644 --- a/astro.sidebar.ts +++ b/astro.sidebar.ts @@ -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', diff --git a/src/content/docs/en/reference/experimental-flags/csp.mdx b/src/content/docs/en/reference/experimental-flags/csp.mdx new file mode 100644 index 0000000000000..95962f4b1b966 --- /dev/null +++ b/src/content/docs/en/reference/experimental-flags/csp.mdx @@ -0,0 +1,406 @@ +--- +title: Experimental Content Security Policy +sidebar: + label: Content Security Policy +i18nReady: true +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 6 +--- + +import Since from '~/components/Since.astro' + +

+ + **Type:** `boolean | object`
+ **Default:** `false`
+ +

+ +Enables support for [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) to help minimize certain types of security threats by controlling which resources a document is allowed to load. This provides additional protection against [cross-site scripting (XSS)](https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting) attacks. + +Enabling this feature adds additional security to **Astro's handling of processed and bundled scripts and styles** by default, and allows you to further configure these, and additional, content types. + +This experimental CSP feature has some limitations. Inline scripts are not supported out of the box, but you can [provide your own hashes](#hashes) for external and inline scripts. Additionally, [Astro's view transitions](/en/guides/view-transitions/) using the `` are not yet fully supported: when navigating from one page to another, some styles may not be applied and some scripts may not be executed. + + +:::note +Due to the nature of the Vite dev server, this feature isn't supported while working in `dev` mode. Instead, you can test this in your Astro project using `build` and `preview`. +::: + +To enable this feature, add the experimental flag in your Astro config: + +```js title="astro.config.mjs" ins={4-6} +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + experimental: { + csp: true + } +}); +``` + +When enabled, Astro will add a `` element inside the `` element of each page. + +This element will have the `http-equiv="content-security-policy"` attribute, and the `content` attribute will provide values for the `script-src` and `style-src` [directives](#directives) based on the script and styles used in the page. + +```html + + + +``` + +## Configuration + +You can further customize the `` element by enabling this feature with a configuration object that includes additional options. + +### `algorithm` + +

+ +**Type:** `'SHA-256' | 'SHA-512' | 'SHA-384'`
+**Default:** `'SHA-256'`
+ +

+ +The [hash function](https://developer.mozilla.org/en-US/docs/Glossary/Hash_function) to use when generating the hashes of the styles and scripts emitted by Astro. + + +```js title="astro.config.mjs" +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + experimental: { + csp: { + algorithm: 'SHA-512' + } + } +}); +``` + +### `directives` + +

+ +**Type:** `CspDirective[]`
+**Default:** `[]`
+ +

+ +A list of [CSP directives](https://content-security-policy.com/#directive) that defines valid sources for specific content types. + +While Astro needs to control the `script-src` and `style-src` directives, it is possible to control other CSP directives using the `csp.directives` 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 `` element will add your directives into the `content` value alongside Astro's default directives: + +```html + +``` + +### `styleDirective` and `scriptDirective` + +

+ +**Type:** `object`
+**Default:** `{}`
+ +

+ +Configuration objects that allow you to override the default sources for the `style-src` and `script-src` directives with the [`resources`](#resources) property, or to provide additional [hashes](#hashes) to be rendered. + +These properties are added to all pages and **completely override Astro's default resources**, not add to them. Therefore, you must explicitly specify any default values that you want to be included. + +#### `resources` + +

+ +**Type:** `string[]`
+**Default:** `[]`
+ +

+ +A list of valid sources for the `script-src` and `style-src` directives. + +The `script-src` and `style-src` directives are handled by Astro by default, and use the `'self'` resource. This means that scripts and styles can only be downloaded by the current host (usually the current website). + +To override the default source, you can provide a list of resources instead. This will not include `'self'` by default, and must be included in this list if you wish to keep it. These resources are added to all pages. + +```js title="astro.config.mjs" +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + experimental: { + csp: { + styleDirective: { + resources: [ + "self", + "https://styles.cdn.example.com" + ] + }, + scriptDirective: { + resources: [ + "https://cdn.example.com" + ] + } + } + } +}); +``` + +After the build, the `` element will instead apply your sources to the `style-src` and `script-src` directives: + +```html + + + +``` + +#### `hashes` + +

+ +**Type:** `CspHash[]`
+**Default:** `[]`
+ +

+ +A list of additional hashes to be rendered. + +If you have external scripts or styles that aren't generated by Astro, or inline scripts, this configuration option 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: { + styleDirective: { + hashes: [ + "sha384-styleHash", + "sha512-styleHash", + "sha256-styleHash" + ] + }, + scriptDirective: { + hashes: [ + "sha384-scriptHash", + "sha512-scriptHash", + "sha256-scriptHash" + ] + } + } + } +}); +``` + +After the build, the `` element will include your additional hashes in the `script-src` and `style-src` directives: + +```html + +``` + +#### `strictDynamic` + +

+ +**Type:** `boolean`
+**Default:** `false`
+ +

+ +Enables [the `strict-dynamic` keyword](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP#the_strict-dynamic_keyword) to support the dynamic injection of scripts. + +```js title="astro.config.mjs" +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + experimental: { + csp: { + scriptDirective: { + strictDynamic: true + } + } + } +}); +``` +## Runtime APIs + +You can customize the `` element per page via runtime APIs available from the `Astro` global inside `.astro` components, or the `APIContext` type in endpoints and middleware. + +### `addDirective` + +

+ **Type:** `(directive: CspDirective) => void`
+ +

+ +Adds a single directive to the current page. You can call this method multiple times to add additional directives. + +```astro +--- +Astro.addDirective("default-src 'self'"); +Astro.addDirective("img-src 'self' 'https://images.cdn.example.com'"); +--- +``` + +After the build, the `` element for this individual page will add your directives to the included `style-src` and `script-src` directives: + +```html + +``` + +### `insertStyleResource` + +

+ **Type:** `(resource: string) => void`
+ +

+ +Inserts a new resource to be used for the `style-src` directive. + +```astro +--- +Astro.insertStyleResource("'https://styles.cdn.example.com'"); +--- +``` + +After the build, the `` element for this individual page will add your source to the default `style-src` directive: + +```html + +``` + + +### `addStyleHash` + +

+ **Type:** `(hash: CspHash) => void`
+ +

+ +Adds a new hash to the `style-src` directive. + +```astro +--- +Astro.addStyleHash("sha512-styleHash"); +--- +``` + +After the build, the `` element for this individual page will add your hash to the default `style-src` directive: + +```html + +``` + + +### `insertScriptResource` + +

+ **Type:** `(resource: string) => void`
+ +

+ +Inserts a new valid source to be used for the `script-src` directive. + + +```astro +--- +Astro.insertScriptResource("'https://scripts.cdn.example.com'"); +--- +``` + +After the build, the `` element for this individual page will add your source to the default `script-src` directive: + +```html + +``` + +### `addScriptHash` + +

+ **Type:** `(hash: CspHash) => void`
+ +

+ +Adds a new hash to the `script-src` directive. + + +```astro +--- +Astro.addScriptHash("sha512-scriptHash"); +--- +``` + +After the build, the `` element for this individual page will add your hash to the default `script-src` directive: + +```html + +```