Skip to content

Apply a CSP in non-Development environments #31106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 28, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 116 additions & 46 deletions aspnetcore/blazor/security/content-security-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,68 @@ Use a `<meta>` tag to apply the policy:

The following sections show example policies. These examples are versioned with this article for each release of Blazor. To use a version appropriate for your release, select the document version with the **Version** dropdown selector on this webpage.

### Server-side Blazor apps

In the [`<head>` content](xref:blazor/project-structure#location-of-head-and-body-content), apply the directives described in the *Policy directives* section:

:::moniker range=">= aspnetcore-6.0"

```html
<meta http-equiv="Content-Security-Policy"
content="base-uri 'self';
default-src 'self';
img-src data: https:;
object-src 'none';
script-src 'self';
style-src 'self';
upgrade-insecure-requests;">
```

:::moniker-end

:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"

```html
<meta http-equiv="Content-Security-Policy"
content="base-uri 'self';
default-src 'self';
img-src data: https:;
object-src 'none';
script-src https://stackpath.bootstrapcdn.com/
'self';
style-src https://stackpath.bootstrapcdn.com/
'self'
'unsafe-inline';
upgrade-insecure-requests;">
```

:::moniker-end

:::moniker range="< aspnetcore-5.0"

```html
<meta http-equiv="Content-Security-Policy"
content="base-uri 'self';
default-src 'self';
img-src data: https:;
object-src 'none';
script-src https://stackpath.bootstrapcdn.com/
'self'
'sha256-34WLX60Tw3aG6hylk0plKbZZFXCuepeQ6Hu7OqRf8PI=';
style-src https://stackpath.bootstrapcdn.com/
'self'
'unsafe-inline';
upgrade-insecure-requests;">
```

:::moniker-end

Add additional `script-src` and `style-src` hashes as required by the app. During development, use an online tool or browser developer tools to have the hashes calculated for you. For example, the following browser tools console error reports the hash for a required script not covered by the policy:

> Refused to execute inline script because it violates the following Content Security Policy directive: " ... ". Either the 'unsafe-inline' keyword, a hash ('sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA='), or a nonce ('nonce-...') is required to enable inline execution.

The particular script associated with the error is displayed in the console next to the error.

### Client-side Blazor apps

In the [`<head>` content](xref:blazor/project-structure#location-of-head-and-body-content), apply the directives described in the *Policy directives* section:
Expand Down Expand Up @@ -243,67 +305,74 @@ Add additional `script-src` and `style-src` hashes as required by the app. Durin

The particular script associated with the error is displayed in the console next to the error.

### Server-side Blazor apps
:::moniker range=">= aspnetcore-8.0"

In the [`<head>` content](xref:blazor/project-structure#location-of-head-and-body-content), apply the directives described in the *Policy directives* section:
## Apply a CSP in non-Development environments

:::moniker range=">= aspnetcore-6.0"
When a CSP is applied to a Blazor app's `<head>` content, it interferes with local testing in the Development environment. For example, [Browser Link](xref:client-side/using-browserlink) and the browser refresh script fail to load. The following examples demonstrate how to apply the CSP's `<meta>` tag in non-Development environments.

```html
<meta http-equiv="Content-Security-Policy"
content="base-uri 'self';
default-src 'self';
img-src data: https:;
object-src 'none';
script-src 'self';
style-src 'self';
upgrade-insecure-requests;">
> [!NOTE]
> The examples in this section don't show the full `<meta>` tag for the CSPs. The complete `<meta>` tags are found in the subsections of the [Apply the policy](#apply-the-policy) section earlier in this article.

Three general approaches are available:

* Apply the CSP via the `App` component, which applies the CSP to all layouts of the app.
* If you need to apply CSPs to different areas of the app, for example a custom CSP for only the admin pages, apply the CSPs on a per-layout basis using the [`<HeadContent>` tag](xref:blazor/components/control-head-content). For complete effectiveness, every app layout file must adopt the approach.
* The hosting service or server can provide a CSP via a [`Content-Security-Policy` header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy) added an app's outgoing responses. Because this approach varies by hosting service or server, it isn't addressed in the following examples. If you wish to adopt this approach, consult the documentation for your hosting service provider or server.

### Blazor Web App approaches

In the `App` component (`Components/App.razor`), inject <xref:Microsoft.Extensions.Hosting.IHostEnvironment>:

```razor
@inject IHostEnvironment Env
```

:::moniker-end
In the `App` component's `<head>` content, apply the CSP when not in the Development environment:

:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0"
```razor
@if (!Env.IsDevelopment())
{
<meta ...>
}
```

```html
<meta http-equiv="Content-Security-Policy"
content="base-uri 'self';
default-src 'self';
img-src data: https:;
object-src 'none';
script-src https://stackpath.bootstrapcdn.com/
'self';
style-src https://stackpath.bootstrapcdn.com/
'self'
'unsafe-inline';
upgrade-insecure-requests;">
Alternatively, apply CSPs on a per-layout basis in the `Components/Layout` folder, as the following example demonstrates. Make sure that every layout specifies a CSP.

```razor
@inject IHostEnvironment Env

@if (!Env.IsDevelopment())
{
<HeadContent>
<meta ...>
</HeadContent>
}
```

:::moniker-end
### Blazor WebAssembly app approaches

:::moniker range="< aspnetcore-5.0"
In the `App` component (`App.razor`), inject <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment>:

```html
<meta http-equiv="Content-Security-Policy"
content="base-uri 'self';
default-src 'self';
img-src data: https:;
object-src 'none';
script-src https://stackpath.bootstrapcdn.com/
'self'
'sha256-34WLX60Tw3aG6hylk0plKbZZFXCuepeQ6Hu7OqRf8PI=';
style-src https://stackpath.bootstrapcdn.com/
'self'
'unsafe-inline';
upgrade-insecure-requests;">
```razor
@using Microsoft.AspNetCore.Components.WebAssembly.Hosting
@inject IWebAssemblyHostEnvironment Env
```

:::moniker-end
In the `App` component's `<head>` content, apply the CSP when not in the Development environment:

Add additional `script-src` and `style-src` hashes as required by the app. During development, use an online tool or browser developer tools to have the hashes calculated for you. For example, the following browser tools console error reports the hash for a required script not covered by the policy:
```razor
@if (!Env.IsDevelopment())
{
<HeadContent>
<meta ...>
</HeadContent>
}
```

> Refused to execute inline script because it violates the following Content Security Policy directive: " ... ". Either the 'unsafe-inline' keyword, a hash ('sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA='), or a nonce ('nonce-...') is required to enable inline execution.
Alternatively, use the preceding code but apply CSPs on a per-layout basis in the `Layout` folder. Make sure that every layout specifies a CSP.

The particular script associated with the error is displayed in the console next to the error.
:::moniker-end

## Meta tag limitations

Expand Down Expand Up @@ -341,6 +410,7 @@ Test and update an app's policy every release.
## Additional resources

* [Apply a CSP in C# code at startup](xref:blazor/fundamentals/startup#control-headers-in-c-code)
* [MDN web docs: Content-Security-Policy](https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy)
* [MDN web docs: Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)
* [MDN web docs: Content-Security-Policy response header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy)
* [Content Security Policy Level 2](https://www.w3.org/TR/CSP2/)
* [Google CSP Evaluator](https://csp-evaluator.withgoogle.com/)