Angelo.Security
1.0.8
dotnet add package Angelo.Security --version 1.0.8
NuGet\Install-Package Angelo.Security -Version 1.0.8
<PackageReference Include="Angelo.Security" Version="1.0.8" />
<PackageVersion Include="Angelo.Security" Version="1.0.8" />
<PackageReference Include="Angelo.Security" />
paket add Angelo.Security --version 1.0.8
#r "nuget: Angelo.Security, 1.0.8"
#:package Angelo.Security@1.0.8
#addin nuget:?package=Angelo.Security&version=1.0.8
#tool nuget:?package=Angelo.Security&version=1.0.8
SecurityMiddleware
Secure-by-default security headers middleware for ASP.NET Core. Provides best-practice security headers with zero configuration, while offering a fluent API for customization when needed.
Table of Contents
- Installation
- Basic Usage
- Default Headers
- Content Security Policy
- Other Security Headers
- Permissions Policy
- Presets
- Environment-Aware Configuration
- Migration Guide
- API Reference
Installation
Add the Angelo.Security nuget package:
dotnet add package Angelo.Security
Basic Usage
Simplest Form
var app = builder.Build();
app.UseSecurity(); // That's it
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
With Configuration
app.UseSecurity(options =>
{
options.ContentSecurityPolicy
.AllowScripts("https://cdn.example.com")
.AllowInlineStyles();
});
With Environment
app.UseSecurity(app.Environment, options =>
{
options.ContentSecurityPolicy.AllowFrames("https://youtube.com");
});
Default Headers
When you call app.UseSecurity() with no configuration, you get:
| Header | Value | Purpose |
|---|---|---|
X-Content-Type-Options |
nosniff |
Prevents MIME-type sniffing |
X-Frame-Options |
DENY |
Prevents clickjacking |
Referrer-Policy |
strict-origin-when-cross-origin |
Controls referrer information |
Strict-Transport-Security |
max-age=31536000; includeSubDomains |
Enforces HTTPS |
Content-Security-Policy |
See below | Controls resource loading |
Permissions-Policy |
Restrictive | Disables dangerous browser features |
Cross-Origin-Opener-Policy |
same-origin |
Isolates browsing context |
Cross-Origin-Resource-Policy |
same-origin |
Controls cross-origin resource sharing |
Default Content Security Policy
default-src 'self';
script-src 'self';
style-src 'self';
img-src 'self' data:;
font-src 'self';
connect-src 'self';
frame-src 'none';
frame-ancestors 'none';
form-action 'self';
base-uri 'self';
object-src 'none';
upgrade-insecure-requests;
Content Security Policy
The CSP configuration uses a fluent builder pattern for readability.
Adding Sources
options.ContentSecurityPolicy
.AllowScripts("https://cdn.example.com", "https://analytics.example.com")
.AllowStyles("https://fonts.googleapis.com")
.AllowFonts("https://fonts.gstatic.com")
.AllowImages("https:", "data:", "blob:")
.AllowConnections("https://api.example.com", "wss://socket.example.com")
.AllowFrames("https://youtube.com", "https://vimeo.com")
.AllowMedia("https://media.example.com")
.AllowWorkers("https://worker.example.com")
.AllowManifest("https://app.example.com");
Allowing Unsafe Directives
Use these sparingly—they weaken CSP protection:
options.ContentSecurityPolicy
.AllowInlineScripts() // Adds 'unsafe-inline' to script-src
.AllowInlineStyles() // Adds 'unsafe-inline' to style-src
.AllowEval(); // Adds 'unsafe-eval' to script-src
Data and Blob URIs
options.ContentSecurityPolicy
.AllowDataUri("img-src", "font-src") // Adds data: to specified directives
.AllowBlobUri("worker-src", "img-src"); // Adds blob: to specified directives
Frame Ancestors
Control which sites can embed your page in an iframe:
// Allow specific parents to embed this page
options.ContentSecurityPolicy
.AllowFrameAncestors("https://parent-site.com", "https://partner.com");
Custom Directives
For directives not covered by helper methods:
options.ContentSecurityPolicy
.SetDirective("require-trusted-types-for", "'script'")
.AddToDirective("script-src", "https://additional-source.com")
.RemoveDirective("object-src");
Report-Only Mode
Test CSP changes without breaking your site:
options.ContentSecurityPolicy.ReportOnly = true;
options.ContentSecurityPolicy.ReportUri = "/api/csp-violations";
Disable Upgrade Insecure Requests
options.ContentSecurityPolicy.UpgradeInsecureRequests = false;
Other Security Headers
X-Frame-Options
options.FrameOptions = FrameOptions.Deny; // Cannot be framed (default)
options.FrameOptions = FrameOptions.SameOrigin; // Can be framed by same origin
Referrer-Policy
options.ReferrerPolicy = ReferrerPolicy.NoReferrer;
options.ReferrerPolicy = ReferrerPolicy.Origin;
options.ReferrerPolicy = ReferrerPolicy.StrictOriginWhenCrossOrigin; // default
// Also: NoReferrerWhenDowngrade, OriginWhenCrossOrigin, SameOrigin, StrictOrigin, UnsafeUrl
Strict-Transport-Security (HSTS)
options.Hsts.Enabled = true; // default
options.Hsts.MaxAge = 31536000; // 1 year (default)
options.Hsts.IncludeSubDomains = true; // default
options.Hsts.Preload = false; // Enable when ready for HSTS preload list
Cross-Origin Policies
// Cross-Origin-Opener-Policy
options.CrossOriginOpenerPolicy = CrossOriginOpenerPolicy.SameOrigin; // default
options.CrossOriginOpenerPolicy = CrossOriginOpenerPolicy.SameOriginAllowPopups;
options.CrossOriginOpenerPolicy = CrossOriginOpenerPolicy.UnsafeNone;
// Cross-Origin-Embedder-Policy
options.CrossOriginEmbedderPolicy = CrossOriginEmbedderPolicy.None; // default (disabled)
options.CrossOriginEmbedderPolicy = CrossOriginEmbedderPolicy.RequireCorp;
options.CrossOriginEmbedderPolicy = CrossOriginEmbedderPolicy.Credentialless;
// Cross-Origin-Resource-Policy
options.CrossOriginResourcePolicy = CrossOriginResourcePolicy.SameOrigin; // default
options.CrossOriginResourcePolicy = CrossOriginResourcePolicy.SameSite;
options.CrossOriginResourcePolicy = CrossOriginResourcePolicy.CrossOrigin;
Remove Identifying Headers
options.RemoveServerHeader = true; // Removes Server header (default)
options.RemovePoweredByHeader = true; // Removes X-Powered-By header (default)
Permissions Policy
Controls which browser features your site can use. Restrictive by default.
Default Disabled Features
- geolocation
- microphone
- camera
- payment
- usb
- magnetometer
- gyroscope
- accelerometer
Configuration
options.PermissionsPolicy
.Disable("geolocation") // Disable entirely
.AllowSelf("camera") // Allow for same origin only
.AllowAll("fullscreen") // Allow for all origins
.Allow("microphone", "https://call.example.com") // Allow for specific origin
.Remove("accelerometer"); // Remove from policy
Presets
Pre-configured security settings for common scenarios.
Strict
Maximum security for sensitive applications (banking, healthcare):
app.UseSecurity(options => options.ApplyPreset(SecurityPresets.Strict));
default-src 'none'- Full cross-origin isolation
- HSTS preload enabled
Standard
Balanced security and compatibility (default behavior with inline styles):
app.UseSecurity(options => options.ApplyPreset(SecurityPresets.Standard));
Api
Optimized for REST APIs:
app.UseSecurity(options => options.ApplyPreset(SecurityPresets.Api));
- Minimal CSP (no script/style/img sources)
- No frame-related directives
SinglePageApp
For SPAs with external API connections:
app.UseSecurity(options => options.ApplyPreset(SecurityPresets.SinglePageApp));
- Allows inline styles
- Allows HTTPS connections
Marketing
For marketing sites with analytics, videos, social embeds:
app.UseSecurity(options => options.ApplyPreset(SecurityPresets.Marketing));
- Google Analytics, Tag Manager, Facebook
- YouTube, Vimeo embeds
- Inline scripts and styles
Legacy
Relaxed settings for legacy applications being migrated:
app.UseSecurity(options => options.ApplyPreset(SecurityPresets.Legacy));
- Allows eval()
- SameOrigin frame options
Combining Presets with Custom Config
app.UseSecurity(options =>
{
options.ApplyPreset(SecurityPresets.Marketing);
options.ContentSecurityPolicy.AllowScripts("https://my-custom-cdn.com");
options.Hsts.Preload = true;
});
Environment-Aware Configuration
The middleware automatically detects the development environment and applies appropriate settings.
Automatic Detection
app.UseSecurity(options =>
{
// In development: CSP automatically allows ws:/wss: and localhost connections
options.ContentSecurityPolicy.AllowFrames("https://youtube.com");
});
Explicit Environment
app.UseSecurity(app.Environment, options =>
{
options.ContentSecurityPolicy.AllowFrames("https://youtube.com");
});
Development Settings Applied
When IsDevelopment() is true:
connect-srcincludesws:,wss:,http://localhost:*,https://localhost:*script-srcincludes'unsafe-inline'style-srcincludes'unsafe-inline'
Migration Guide
Before
app.Use(async (context, next) =>
{
var headers = context.Response.Headers;
headers["X-Content-Type-Options"] = "nosniff";
headers["X-Frame-Options"] = "DENY";
headers["Referrer-Policy"] = "strict-origin-when-cross-origin";
headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains";
string csp;
if (app.Environment.IsDevelopment())
{
csp = "default-src 'self' ws: wss:; " +
"script-src 'self' 'unsafe-inline' https://esm.sh; " +
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " +
"font-src 'self' https://fonts.gstatic.com; " +
"img-src 'self' data: https:; " +
"connect-src 'self' ws: wss: http://localhost:* https://esm.sh; " +
"form-action 'self'; " +
"base-uri 'self'; " +
"frame-src https://www.youtube.com https://www.youtube-nocookie.com; " +
"object-src 'none'; " +
"frame-ancestors 'none';";
}
else
{
csp = "default-src 'self'; " +
"script-src 'self' 'unsafe-inline' https://esm.sh; " +
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " +
"font-src 'self' https://fonts.gstatic.com; " +
"img-src 'self' data: https:; " +
"connect-src 'self'; " +
"frame-src https://www.youtube.com https://www.youtube-nocookie.com; " +
"form-action 'self'; " +
"base-uri 'self'; " +
"object-src 'none'; " +
"frame-ancestors 'none';";
}
headers["Content-Security-Policy"] = csp;
await next();
});
After
app.UseSecurity(options =>
{
options.ContentSecurityPolicy
.AllowInlineScripts()
.AllowInlineStyles()
.AllowScripts("https://esm.sh")
.AllowStyles("https://fonts.googleapis.com")
.AllowFonts("https://fonts.gstatic.com")
.AllowImages("data:", "https:")
.AllowConnections("https://esm.sh")
.AllowFrames("https://www.youtube.com", "https://www.youtube-nocookie.com");
});
Development settings (ws:/wss:/localhost) are applied automatically.
API Reference
SecurityExtensions
| Method | Description |
|---|---|
UseSecurity() |
Apply secure defaults |
UseSecurity(Action<SecurityOptions>) |
Apply with configuration |
UseSecurity(IWebHostEnvironment, Action<SecurityOptions>?) |
Apply with explicit environment |
SecurityOptions
| Property | Type | Default | Description |
|---|---|---|---|
ContentSecurityPolicy |
CspOptions |
Restrictive | CSP configuration |
FrameOptions |
FrameOptions |
Deny |
X-Frame-Options value |
NoSniff |
bool |
true |
X-Content-Type-Options: nosniff |
ReferrerPolicy |
ReferrerPolicy |
StrictOriginWhenCrossOrigin |
Referrer-Policy value |
Hsts |
HstsOptions |
Enabled, 1 year | HSTS configuration |
PermissionsPolicy |
PermissionsPolicyOptions |
Restrictive | Permissions-Policy configuration |
CrossOriginOpenerPolicy |
CrossOriginOpenerPolicy |
SameOrigin |
COOP value |
CrossOriginEmbedderPolicy |
CrossOriginEmbedderPolicy |
None |
COEP value |
CrossOriginResourcePolicy |
CrossOriginResourcePolicy |
SameOrigin |
CORP value |
RemoveServerHeader |
bool |
true |
Remove Server header |
RemovePoweredByHeader |
bool |
true |
Remove X-Powered-By header |
CspOptions Methods
| Method | Description |
|---|---|
AllowScripts(params string[]) |
Add sources to script-src |
AllowStyles(params string[]) |
Add sources to style-src |
AllowImages(params string[]) |
Add sources to img-src |
AllowFonts(params string[]) |
Add sources to font-src |
AllowConnections(params string[]) |
Add sources to connect-src |
AllowFrames(params string[]) |
Add sources to frame-src |
AllowFrameAncestors(params string[]) |
Add sources to frame-ancestors |
AllowFormAction(params string[]) |
Add sources to form-action |
AllowMedia(params string[]) |
Add sources to media-src |
AllowWorkers(params string[]) |
Add sources to worker-src |
AllowManifest(params string[]) |
Add sources to manifest-src |
AllowInlineScripts() |
Add 'unsafe-inline' to script-src |
AllowInlineStyles() |
Add 'unsafe-inline' to style-src |
AllowEval() |
Add 'unsafe-eval' to script-src |
AllowDataUri(params string[]) |
Add data: to specified directives |
AllowBlobUri(params string[]) |
Add blob: to specified directives |
SetDirective(string, params string[]) |
Set directive value (replaces existing) |
AddToDirective(string, params string[]) |
Add to existing directive |
RemoveDirective(string) |
Remove directive entirely |
ApplyDevelopmentSettings() |
Apply dev-friendly settings |
PermissionsPolicyOptions Methods
| Method | Description |
|---|---|
Disable(string) |
Disable feature entirely |
AllowSelf(string) |
Allow feature for same origin |
AllowAll(string) |
Allow feature for all origins |
Allow(string, params string[]) |
Allow feature for specific origins |
Remove(string) |
Remove feature from policy |
SecurityPresets
| Preset | Use Case |
|---|---|
Strict |
Banking, healthcare, high-security apps |
Standard |
General web applications |
Api |
REST APIs |
SinglePageApp |
React, Vue, Angular apps |
Marketing |
Marketing sites with analytics/embeds |
Legacy |
Legacy apps being migrated |
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-windows7.0 is compatible. |
-
net10.0-windows7.0
- Microsoft.EntityFrameworkCore (>= 10.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.