Swallow.ContentSecurityPolicy
1.0.0
dotnet add package Swallow.ContentSecurityPolicy --version 1.0.0
NuGet\Install-Package Swallow.ContentSecurityPolicy -Version 1.0.0
<PackageReference Include="Swallow.ContentSecurityPolicy" Version="1.0.0" />
<PackageVersion Include="Swallow.ContentSecurityPolicy" Version="1.0.0" />
<PackageReference Include="Swallow.ContentSecurityPolicy" />
paket add Swallow.ContentSecurityPolicy --version 1.0.0
#r "nuget: Swallow.ContentSecurityPolicy, 1.0.0"
#:package Swallow.ContentSecurityPolicy@1.0.0
#addin nuget:?package=Swallow.ContentSecurityPolicy&version=1.0.0
#tool nuget:?package=Swallow.ContentSecurityPolicy&version=1.0.0
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 | Versions 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. |
-
net10.0
- Swallow.ContentSecurityPolicy.Abstractions (>= 1.0.0)
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 |