Swallow.ContentSecurityPolicy 1.0.0

dotnet add package Swallow.ContentSecurityPolicy --version 1.0.0
                    
NuGet\Install-Package Swallow.ContentSecurityPolicy -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Swallow.ContentSecurityPolicy" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Swallow.ContentSecurityPolicy" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Swallow.ContentSecurityPolicy" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Swallow.ContentSecurityPolicy --version 1.0.0
                    
#r "nuget: Swallow.ContentSecurityPolicy, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Swallow.ContentSecurityPolicy@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Swallow.ContentSecurityPolicy&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Swallow.ContentSecurityPolicy&version=1.0.0
                    
Install as a Cake Tool

Swallow.ContentSecurityPolicy

A neat Content Security Policy (CSP) integration for ASP.NET Core. Because after all this time, there isn't really a built-in way to do that, especially when working with a nonce.

Getting started

See the demo host for full example.

Register the services

builder.Services.AddContentSecurityPolicy(
    opt => opt
        .SetFallbackPolicy(b => b.AddDefaultSource(Allow.Nothing))
        .SetDefaultPolicy(b => b.AddDefaultSource(Allow.Self, Allow.Nonce))
        .AddPolicy("Special", b => b.AddDefaultSource(Allow.UnsafeInline))
    );

The policies are similar to authorization policies:

  • The fallback policy is used when an endpoint does not define a policy
  • The default policy is used when an endpoint defines a policy but does not require a specific policy
  • A specific policy is used when an endpoint refers to that policy by its name

Add the middleware

app.UseContentSecurityPolicy();

It should be placed after UseRouting() because the middleware tries to read metadata from the resolved endpoint. If you do not specify UseRouting() by yourself, it doesn't matter - you'll be safe!

Apply a policy to an endpoint

app.MapGet("/", () => "I have the fallback policy");
app.MapGet("/default", () => "I have the default policy").WithContentSecurityPolicy();
app.MapGet("/specific", () => "I have a specific policy").WithContentSecurityPolicy("Special");
app.MapGet("/ignored", () => "I don't have any policy").DisableContentSecurityPolicy();

You can also use the attributes directly: ContentSecurityPolicyAttribute and DisableContentSecurityPolicyAttribute.

While you can add multiple WithContentSecurityPolicy()-calls to a single endpoint, only the last one is considered. As soon as you use DisableContentSecurityPolicy(), all other calls to WithContentSecurityPolicy() are ignored; this is very similar to [Authorize] and [AllowAnonymous].

Use a nonce

If your policy is configured to allow a nonce, you can access that nonce via the HttpContext:

builder.Services.AddContentSecurityPolicy(
    opt => opt.SetFallbackPolicy(b => b.AddDefaultSource(Allow.Nonce)));

// ... later
app.UseContentSecurityPolicy();
app.MapGet("/", ctx => ctx.Response.WriteAsync($"The nonce is '{ctx.Nonce}'"));

Reporting violations

To not actually block any resources, but only send reports for resources that would be blocked, you can set ReportOnly on the policy.

builder.Services.AddContentSecurityPolicy(opt => opt
    .SetFallbackPolicy(b => b
        .AddDefaultSource(Allow.Nothing)
        .ReportOnly()));

This only makes sense when actually setting a reporting endpoint, though.

builder.Services.AddContentSecurityPolicy(opt => opt
    .SetFallbackPolicy(b => b
        .AddDefaultSource(Allow.Nothing)
        .SendReportsTo("/reports")
        .ReportOnly()));

Handling violation reports

Most of the time, you want to handle the CSP violations in the same host that defines them. To do that, you can implement one (or more) IReportHandlers. To automatically wire up the handler to the report-to directive, you can use SendReportsToLocal:

builder.Services.AddContentSecurityPolicy(opt => opt
    .SetFallbackPolicy(b => b
        .AddDefaultSource(Allow.Nothing)
        .SendReportsToLocal()
        .ReportOnly()));

builder.Services.AddContentSecurityPolicyReportHandler<MyHandler>();
// ...or builder.Services.AddScoped<IReportHandler, MyHandler>()

The URL of the reporting endpoint is resolved automatically once you map the endpoint:

// Handles reports on _framework/content-security-policy/violations by default
app.MapContentSecurityPolicyViolations();

// You can also pass in a custom route if you want:
app.MapContentSecurityPolicyViolations(route: "custom-report-route");

The report handler itself can be fairly simple:

public sealed class ReportHandler(ILogger<ReportHandler> logger) : IReportHandler
{
    public Task Handle(ViolationReport[] violationReports, CancellationToken cancellationToken)
    {
        foreach (var report in violationReports)
        {
            // Just log them as warnings.
            logger.LogWarning("CSP Violation {Report}", JsonSerializer.Serialize(report));
        }

        return Task.CompletedTask;
    }
}
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 61 4/5/2026