# IM.ContentSecurityPolicy: CSP and nonces for Umbraco \| Idea Makers

Canonical URL: <https://ideamakers.pl/en/nuget/im-contentsecuritypolicy/>

Content Security Policy headers and a fresh nonce for every request, for ASP.NET Core and Umbraco 13 to 18. Tag helper, HTML helpers and Report-Only mode.

IM.ContentSecurityPolicy · Umbraco 13 to 18

# A strict CSP without manual nonces

Content Security Policy headers and a fresh nonce for every request, for ASP.NET Core and Umbraco. The package adds the nonce to your script, style and link tags.

[Get it on NuGet](https://www.nuget.org/packages/IM.ContentSecurityPolicy)

[Umbraco Marketplace](https://marketplace.umbraco.com/)

Package

**Install:** dotnet add package IM.ContentSecurityPolicy

**Version:** 2.0.4

**Umbraco:** 13 to 18

**.NET:** 8, 9, 10

On this page

- What it does
- Get started
- [In your views](https://ideamakers.pl/en/nuget/im-contentsecuritypolicy/#views)
- The policy
- Compatibility
- In use
- Support

What it does

## Three jobs, on every request

01

### A nonce per request

- A random value from a cryptographically secure generator, available to your views and code\.

02

### A CSP header from your settings

- Content\-Security\-Policy, or Report\-Only while you test, built from options you control\.

03

### Nonces on your tags

- Added to script, style and link tags by a tag helper, HTML helpers or view components\.

Get started

## Install and register

01

### Add the package

One package for Umbraco 13 to 18 and plain ASP.NET Core.

```
dotnet add package IM.ContentSecurityPolicy
```

02

### Register the middleware

In Program.cs. Nonce generation comes first, so the header can use the nonce.

```
builder.Services.AddNonceServices();

var app = builder.Build();

app.UseNonceGeneration();
app.UseContentSecurityPolicy();
```

03

### Register the helpers once

In Views/\_ViewImports.cshtml, so every view can add the nonce.

```
@addTagHelper *, IM.ContentSecurityPolicy
@using IM.ContentSecurityPolicy.Extensions
```

In your views

## Four ways to add the nonce

### Tag helper

Add asp-nonce="true" to script, style and link tags. The nonce of the current request is written for you.

```
<script src="~/js/site.js" asp-nonce="true"></script>

<style asp-nonce="true">
  .hero { color: #3544b1; }
</style>

<link rel="stylesheet" href="~/css/site.css" asp-nonce="true" />
```

### HTML helpers

For tags you build in Razor. The helpers do not HTML-encode their input, so pass only trusted values.

```
@Html.ScriptWithNonce("~/js/site.js")
@Html.InlineScriptWithNonce("console.log('ready');")
@Html.StyleWithNonce("~/css/site.css")
@Html.InlineStyleWithNonce(".hero { color: #3544b1; }")

<script @Html.GetNonceAttribute()>
  window.dataLayer = window.dataLayer || [];
</script>
```

### View components

NonceScript, NonceInlineScript, NonceStyle and NonceInlineStyle. Each needs its view, for example Views/Shared/Components/NonceScript/Default.cshtml.

```
@await Component.InvokeAsync("NonceScript", new { src = "~/js/site.js" })
```

### Your own code

Inject INonceService. GetNonce\(\) returns the nonce of the current request and HasNonce\(\) tells you whether one exists.

```
public class ScriptsController(INonceService nonces) : Controller
{
    public IActionResult Index()
    {
        ViewData["Nonce"] = nonces.GetNonce();
        return View();
    }
}
```

The policy

## Test first, then enforce

### Report-Only while you test

The browser reports what the policy would block, and blocks nothing.

- Set ReportOnly and a ReportUri
- See which scripts and styles still lack a nonce
- Visitors notice nothing

### Enforce

Turn Report-Only off once the reports are clean.

- The browser blocks anything without a valid nonce or allowed source
- A fresh nonce on every request
- Keep the ReportUri to catch regressions

Configuration

## Set the sources

Options

### Set the sources

\{nonce\} is replaced on every request.

```
builder.Services.AddNonceServices(options =>
{
    options.ScriptSrc = new[] { "'self'", "'nonce-{nonce}'", "https://cdn.example.com" };
    options.ReportOnly = true;
    options.ReportUri = "/csp-report";
});
```

Builder

### Start from the strict preset

CspOptionsBuilder gives you a strict policy to extend.

```
var options = CspOptionsBuilder.CreateStrict()
    .WithScriptSrc("'self'", "'nonce-{nonce}'")
    .WithReportUri("/csp-report")
    .Build();
```

Compatibility

## One package, Umbraco 13 to 18

| Umbraco | \.NET | Package version |
| --- | --- | --- |
| 13 LTS, 14 | 8 | 2\.x |
| 15, 16 | 9 | 2\.x |
| 17 LTS, 18 | 10 | 2\.x |
| 10 to 12 | 6, 7 | 1\.0\.2 |

In use

## On our own site

01 · Response header

### The policy ideamakers.pl sends

Scripts and styles run only from our own domain or with the nonce of the request. No 'unsafe-inline', no plugins, no framing by other sites.

```
Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-qTQx0elxVNpegG/7B+tAYA==' https://challenges.cloudflare.com;
  style-src 'self' 'nonce-qTQx0elxVNpegG/7B+tAYA==' 'sha256-Kh2l25Sy4DYc/g2Mm3KwI0W8tow97xzNP6zUE8/2UHE=';
  img-src 'self' data:;
  font-src 'self' data:;
  connect-src 'self';
  frame-src 'self' https://challenges.cloudflare.com;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'self'
```

02 · Two requests

### A new nonce every time

The same page requested twice gets two different values, so a nonce copied from one response is useless in the next.

```
GET https://ideamakers.pl/en/contact/
  script-src 'self' 'nonce-74KxrM8xVoaTobkUhxHTZA==' ...

GET https://ideamakers.pl/en/contact/
  script-src 'self' 'nonce-qTQx0elxVNpegG/7B+tAYA==' ...
```

03 · Page source

### The nonce on every script

Structured data, the consent state and inline scripts all carry the nonce of that response.

```
<script type="application/ld+json" nonce="qTQx0elxVNpegG/7B+tAYA==">
<script id="im-consent-state" type="application/json" nonce="qTQx0elxVNpegG/7B+tAYA==">
<script nonce="qTQx0elxVNpegG/7B+tAYA==">
```

Support

## Questions, bugs and ideas

On GitHub

- [Issue tracker: bugs and feature requests](https://github.com/Idea-Makers/im-contentsecuritypolicy/issues)
- [Discussions: questions and setup help](https://github.com/Idea-Makers/im-contentsecuritypolicy/discussions)
- [Release notes for every version](https://github.com/Idea-Makers/im-contentsecuritypolicy/releases)
- [README: full documentation](https://github.com/Idea-Makers/im-contentsecuritypolicy)

## Want a strict CSP on your Umbraco site?

We can set up the policy, move inline scripts to nonces and test it in Report-Only first.

- Umbraco 13 to 18

[Let’s talk](https://ideamakers.pl/en/contact.md)

[All NuGet packages](https://ideamakers.pl/en/nuget.md)

im-contentsecuritypolicy
