SafeWebCore is a lightweight, high-performance .NET 10 middleware library that adds security headers to your ASP.NET Core applications. It targets an A+ rating on securityheaders.com out of the box — zero configuration required.
Current version: 1.7.0
- 🔒 A+ in one line —
AddNetSecureHeadersStrictAPlus()configures the strictest security headers instantly - 🧭 App-profile presets — ready-made profiles for API, MVC, Blazor, and SPA reverse-proxy apps
- 🛠️ Fully custom —
AddNetSecureHeaders(opts => { ... })gives you complete control over every header - ⚙️ Configuration binding —
AddNetSecureHeadersFromConfiguration(...)bindsNetSecureHeadersOptionsdirectly from configuration - 🌦️ Environment-aware rollout — opt-in helpers can default CSP to report-only outside production for safer rollout
- 🧩 Nonce-based CSP — per-request cryptographic nonces for
script-srcandstyle-src - 🧷 Razor nonce TagHelpers — auto-inject nonce attributes on
<script>and<style>when available - 🛣️ Path-based policies — apply different security profiles per route prefix with longest-prefix matching
- 🎯 Endpoint metadata overrides — skip headers or force CSP report-only per endpoint
- 🧪 Startup configuration validation — invalid combinations fail fast during startup
- 📝 CSP Report-Only support — ship policies safely before enforcing
- 🧱 Typed policy builders — strongly typed builders for
Referrer-Policy,Permissions-Policy, and COEP/COOP/CORP values - 🧰 Optional additional headers — opt-in support for
Origin-Agent-Cluster,X-Robots-Tag, andClear-Site-Data - 📋 Full CSP Level 3 (W3C Recommendation) — all directives including
worker-src,manifest-src,frame-src,script-src-elem/attr,style-src-elem/attr,report-to, nonce/hash support,strict-dynamic - 🔮 CSP Level 4 ready — Trusted Types (
require-trusted-types-for,trusted-types),fenced-frame-src(Privacy Sandbox) - 🎯 Fluent CSP Builder — type-safe, chainable API with full XML documentation for every directive
- ⚡ Zero-allocation nonce generation —
stackalloc+RandomNumberGeneratoron the hot path, plusTryWriteNonce(Span<char>)for fully heap-free scenarios - 🔍
HttpContext.GetCspNonce()— discoverable extension method to retrieve the per-request nonce - 🛑 Server header removal — hides server technology from attackers
- 🔌 Extensible — add custom
IHeaderPolicyimplementations for any header - 📊 CSP violation reporting — built-in middleware for
/csp-reportendpoint using Reporting API v1 - 🔍 Diagnostics preview —
MapSafeWebCoreDiagnostics(...)for an opt-in JSON preview of effective headers, path-policy resolution, and CSP mode - 📈 Opt-in metrics —
System.Diagnostics.Metricscounters for core middleware and fraud detection - 🚨 Fraud action pipeline —
IFraudEventSink/FraudEventfor reacting to fraud analysis results (logging, webhooks, custom actions) - 📦 Companion packages —
SafeWebCore.FraudDetection,SafeWebCore.Analyzers(preview), andSafeWebCore.Testing(preview) - 📖 Recipe docs — practical integration guides under
docs/recipes/ - ✅ Actionable startup validation — remediation guidance for CSP mode, path prefixes, additional headers, and reporting endpoints
usingSafeWebCore.Builder;builder.Services.AddNetSecureHeaders(opts =>{opts.ReferrerPolicyValue=newReferrerPolicyBuilder().StrictOriginWhenCrossOrigin().Build();opts.PermissionsPolicyValue=newPermissionsPolicyBuilder().Disable(PermissionsFeature.Camera).Disable(PermissionsFeature.Microphone).AllowSelf(PermissionsFeature.Geolocation).Build();varcrossOrigin=newCrossOriginPolicyBuilder().CoepRequireCorp().CoopSameOrigin().CorpSameOrigin().Build();opts.CoepValue=crossOrigin.Coep;opts.CoopValue=crossOrigin.Coop;opts.CorpValue=crossOrigin.Corp;});builder.Services.AddNetSecureHeaders(opts =>{opts.EnableOriginAgentCluster=true;opts.OriginAgentClusterValue="?1";opts.EnableXRobotsTag=true;opts.XRobotsTagValue="noindex, nofollow";opts.EnableClearSiteData=true;opts.ClearSiteDataValue="\"cache\", \"cookies\", \"storage\"";});| Standard | Status | Coverage |
|---|---|---|
| CSP Level 3 (W3C Recommendation) | ✅ Full | All 22 directives, nonce/hash, strict-dynamic, report-to |
| CSP Level 4 (Emerging) | ✅ Ready | Trusted Types, fenced-frame-src (Privacy Sandbox) |
v1.7.0 is a security hardening and presets release — fully backwards compatible with v1.6.0 and earlier.
| Improvement | Detail |
|---|---|
| Path policy inheritance | PathPolicy(...) now inherits the global configuration — only explicitly set values override (resolves issue #3, prevents HSTS/CSP downgrades on path-specific endpoints) |
| Public inheritance API | ApplyPreset(...) and Clone() are now public — build path policies and custom presets from an existing options instance |
| OWASP API preset | AddNetSecureHeadersOwaspApiPreset() aligned with the OWASP API Security Top 10 response-header hardening |
| NSwag preset | AddNetSecureHeadersNSwagPreset() for Rico Sutter's NSwag UI with nonce-based CSP and no 'unsafe-inline' (stricter than Swagger) |
See the full CHANGELOG for details.
dotnet add package SafeWebCoreusingSafeWebCore.Extensions;varbuilder=WebApplication.CreateBuilder(args);// Adds ALL security headers with the strictest A+ configurationbuilder.Services.AddNetSecureHeadersStrictAPlus();varapp=builder.Build();app.UseNetSecureHeaders();app.MapGet("/",()=>"Hello, secure world!");app.Run();That's it! Your application now returns these headers on every response:
| Header | Value |
|---|---|
Strict-Transport-Security | max-age=63072000; includeSubDomains; preload |
X-Frame-Options | DENY |
X-Content-Type-Options | nosniff |
Referrer-Policy | no-referrer |
Permissions-Policy | All recognized features denied (scanner-safe) |
Cross-Origin-Embedder-Policy | require-corp |
Cross-Origin-Opener-Policy | same-origin |
Cross-Origin-Resource-Policy | same-origin |
X-DNS-Prefetch-Control | off |
X-Permitted-Cross-Domain-Policies | none |
Content-Security-Policy | Nonce-based, strict-dynamic, Trusted Types |
Server | (removed) |
X-Powered-By | (removed) |
The preset is intentionally strict. Relax only what your app needs. CSP directives are space-separated — add multiple origins in a single string:
builder.Services.AddNetSecureHeadersStrictAPlus(opts =>{// Multiple CDNs — just separate with spacesopts.Csp=opts.Cspwith{ImgSrc="'self' https://cdn1.example.com https://cdn2.example.com data:"};// Multiple directives at once using 'with { ... }'opts.Csp=opts.Cspwith{ConnectSrc="'self' https://api.example.com wss://ws.example.com",FontSrc="'self' https://fonts.gstatic.com https://cdn.example.com"};// Non-CSP headers are simple string propertiesopts.ReferrerPolicyValue="strict-origin-when-cross-origin";});💡 Tip: Each CSP directive is one string with space-separated sources. Use a single
with { ... }block to change multiple directives at once.
For complete control, use AddNetSecureHeaders with the fluent CSP builder:
usingSafeWebCore.Builder;usingSafeWebCore.Extensions;builder.Services.AddNetSecureHeaders(opts =>{opts.EnableHsts=true;opts.HstsValue="max-age=31536000; includeSubDomains";opts.EnableXFrameOptions=true;opts.XFrameOptionsValue="SAMEORIGIN";opts.ReferrerPolicyValue="strict-origin-when-cross-origin";// Use the fluent CSP builderopts.Csp=newCspBuilder().DefaultSrc("'none'").ScriptSrc("'nonce-{nonce}' 'strict-dynamic' https:").StyleSrc("'nonce-{nonce}'").ImgSrc("'self' https: data:").FontSrc("'self' https://fonts.gstatic.com").ConnectSrc("'self' wss://realtime.example.com").FrameAncestors("'none'").BaseUri("'none'").FormAction("'self'").UpgradeInsecureRequests().Build();});The current workspace includes the completed v1.5 tooling features (additive, opt-in, 100% backward compatible):
- SWC001: Registration without
UseNetSecureHeaders() - SWC002: Permanent
UseCspReportOnly = true - SWC003:
'unsafe-inline'without nonce - SWC004: Overly broad CSP sources
AssertHasSecurityHeaders()AssertHasCspEnforceMode()/AssertHasCspReportOnlyMode()AssertHasNonceInCsp()/AssertHasNoNonceInCsp()- Bootstrap helpers for
TestServer
See docs/recipes/ for practical examples.
The following features are now implemented from the v1.2 plan.
builder.Services.AddNetSecureHeaders(opts =>{opts.UseCspReportOnly=true;});This emits Content-Security-Policy-Report-Only instead of enforce-mode Content-Security-Policy.
builder.Services.AddNetSecureHeaders(opts =>{opts.PathPolicies.Add(newPathPolicyOptions{PathPrefix="/api",Options=newNetSecureHeadersOptions{ReferrerPolicyValue="no-referrer",UseCspReportOnly=true}});});Path policies are matched by prefix and the longest matching prefix wins.
SafeWebCore validates options during startup and fails fast for invalid configurations, for example:
UseCspReportOnly = truewhileEnableCsp = false- duplicate path prefixes (normalized)
- empty path policy prefixes
Register the TagHelpers in your Razor _ViewImports.cshtml:
@addTagHelper *, SafeWebCoreThen use normal tags; nonce is added automatically when available:
<script>console.log("nonce is injected automatically");</script><style>body { font-family: sans-serif; }
</style>SafeWebCore generates a unique cryptographic nonce per request. Use it in your scripts and styles:
usingSafeWebCore.Attributes;[CspNonce]publicclassHomeController:Controller{publicIActionResultIndex()=>View();}<!-- In your Razor view --><scriptnonce="@ViewData["CspNonce"]">console.log("This script is allowed by CSP");</script><stylenonce="@ViewData["CspNonce"]">body { font-family: sans-serif; }
</style>usingSafeWebCore.Extensions;// In Minimal APIapp.MapGet("/page",(HttpContextctx)=>{varnonce=ctx.GetCspNonce();returnResults.Content($"<script nonce=\"{nonce}\">console.log('nonce ok');</script>","text/html");});// In a controller actionpublicIActionResultIndex(){ViewData["CspNonce"]=HttpContext.GetCspNonce();returnView();}SafeWebCore ships a BenchmarkDotNet suite covering nonce generation, CSP header assembly, typed policy builders, preset instantiation, the middleware pipeline, and CSP report parsing.
cd benchmarks/SafeWebCore.Benchmarks
dotnet run -c ReleaseSee docs/benchmarks.md for scenario descriptions, running instructions, and result interpretation.
Three complete, runnable ASP.NET Core applications demonstrating different integration patterns:
| Example | Framework | Key Features |
|---|---|---|
| MinimalApi | Minimal API | One-line A+ setup, inline nonce, CSP reporting, health probes |
| MvcApp | MVC + Razor Views | Typed policy builders, path policies, nonce TagHelpers, controller attributes |
| ApiService | Web API Controllers | Custom CSP report sink, endpoint overrides, API preset |
Each example is fully functional out of the box — just dotnet run from the example directory.
# Try each examplecd examples/MinimalApi && dotnet run
cd examples/MvcApp && dotnet run
cd examples/ApiService && dotnet runSee examples/README.md for a detailed overview and feature matrix.
| Guide | Description |
|---|---|
| Getting Started | Installation, minimal setup, and verifying your headers |
| Examples | Three complete sample projects (Minimal API, MVC, Web API) |
| Security Headers | Every security header explained with values and rationale |
| CSP Configuration | CSP builder, nonces, directives, and common scenarios |
| Presets | Strict A+ and app-profile presets, customization examples |
| Advanced Configuration | Custom policies, CSP reporting, endpoint overrides, troubleshooting |
| Benchmarks | Running benchmarks and interpreting results |