QuokkaDev.SecurityHeaders
1.2.4-alpha0
See the version list below for details.
dotnet add package QuokkaDev.SecurityHeaders --version 1.2.4-alpha0
NuGet\Install-Package QuokkaDev.SecurityHeaders -Version 1.2.4-alpha0
<PackageReference Include="QuokkaDev.SecurityHeaders" Version="1.2.4-alpha0" />
paket add QuokkaDev.SecurityHeaders --version 1.2.4-alpha0
#r "nuget: QuokkaDev.SecurityHeaders, 1.2.4-alpha0"
// Install QuokkaDev.SecurityHeaders as a Cake Addin #addin nuget:?package=QuokkaDev.SecurityHeaders&version=1.2.4-alpha0&prerelease // Install QuokkaDev.SecurityHeaders as a Cake Tool #tool nuget:?package=QuokkaDev.SecurityHeaders&version=1.2.4-alpha0&prerelease
QuokkaDev.SecurityHeaders
QuokkaDev.SecurityHeaders is a .NET middleware for adding OWASP security headers to your web applications
Installing QuokkaDev.SecurityHeaders
You should install the package via the .NET command line interface
Install-Package QuokkaDev.SecurityHeaders
Using QuokkaDev.SecurityHeaders
Register the middleware using the extension methods. Call the extension method in the early phase of the pipeline so the security headers will be applied to all responses.
Please note that the middleware apply some default values for headers; if you don't want some headers you must explicitly overrides the values. You can override values programmatically or reading from configuration.
startup.cs
//Use headers with default values
app.UseSecurityHeaders();
//Configure headers programmatically
app.UseSecurityHeaders(settings =>
{
settings.XFrameOption = XFrameOption.deny;
settings.XContentTypeOptions = XContentTypeOptions.nosniff;
settings.UseContentSecurityPolicy = true;
settings.UsePermissionPolicy = true;
settings.XPermittedCrossDomainPolicies = XPermittedCrossDomainPolicies.none;
settings.ReferrerPolicy = ReferrerPolicy.no_referrer;
settings.CrossOriginEmbedderPolicy = CrossOriginEmbedderPolicy.require_corp;
settings.CrossOriginOpenerPolicy = CrossOriginOpenerPolicy.same_origin;
settings.CrossOriginResourcePolicy = CrossOriginResourcePolicy.same_origin;
settings.ClearSiteData = new QuokkaDev.SecurityHeaders.ClearSitedata.ClearSiteData()
.ClearCache()
.ClearCookies()
.ClearStorage();
settings.ContentSecurityPolicy = ContentSecurityPolicyBuilder
.New()
.AddDefaultSrc( directive =>
{
directive.Self();
directive.AddSource("https://my.custom.site");
})
.AddStyleSrc(directive =>
{
directive.Self();
directive.UnsafeInline();
})
.Build();
settings.PermissionPolicy = PermissionPolicyBuilder
.New()
.AddAccelerometer(directive => {
directive.Self();
})
.Build();
});
//Use headers reading from values from configuration in a section named "SecurityHeaders"
app.UseSecurityHeaders(this.Configuration);
//You can also use a custom section name
app.UseSecurityHeaders(this.Configuration, "CustomSectionName");
//You can also read from configuration and programmatically override some values
app.UseSecurityHeaders(this.Configuration, "CustomSectionName", settings =>
{
settings.XFrameOption = XFrameOption.none;
});
Available headers
X-Frame-Options
Admitted values:
- none (don't use header)
- deny (default value)
- sameorigin
app.UseSecurityHeaders(settings =>
{
settings.XFrameOption = XFrameOption.sameorigin;
});
{
"SecurityHeaders": {
"XFrameOption": "sameorigin"
}
}
X-Content-Type-Options
Admitted values:
- none (don't use header)
- nosniff (default value)
app.UseSecurityHeaders(settings =>
{
settings.XContentTypeOptions = XContentTypeOptions.nosniff;
});
{
"SecurityHeaders": {
"XContentTypeOptions": "nosniff"
}
}
X-Permitted-Cross-Domain-Policies
Admitted values:
- no_header (don't use header)
- none (default value)
- master_only
- by_content_type
- by_ftp_filename
- all
app.UseSecurityHeaders(settings =>
{
settings.XPermittedCrossDomainPolicies = XPermittedCrossDomainPolicies.none;
});
{
"SecurityHeaders": {
"XPermittedCrossDomainPolicies": "none"
}
}
Referrer-Policy
Admitted values:
- none (don't use header)
- no_referrer (default value)
- no_referrer_when_downgrade
- origin
- origin_when_cross_origin
- same_origin
- strict_origin
- strict_origin_when_cross_origin
- unsafe_url
app.UseSecurityHeaders(settings =>
{
settings.ReferrerPolicy = ReferrerPolicy.no_referrer;
});
{
"SecurityHeaders": {
"ReferrerPolicy": "no_referrer"
}
}
Cross-Origin-Embedder-Policy
Admitted values:
- none (don't use header)
- unsafe_none
- require_corp (default value)
app.UseSecurityHeaders(settings =>
{
settings.CrossOriginEmbedderPolicy = CrossOriginEmbedderPolicy.require_corp;
});
{
"SecurityHeaders": {
"CrossOriginEmbedderPolicy": "require_corp"
}
}
Cross-Origin-Opener-Policy
Admitted values:
- none (don't use header)
- unsafe_none
- same_origin_allow_popups
- same_origin (default value)
app.UseSecurityHeaders(settings =>
{
settings.CrossOriginOpenerPolicy = CrossOriginOpenerPolicy.same_origin;
});
{
"SecurityHeaders": {
"CrossOriginOpenerPolicy": "same_origin"
}
}
Cross-Origin-Resource-Policy
Admitted values:
- none (don't use header)
- same_site
- same_origin (default value)
- cross_origin
app.UseSecurityHeaders(settings =>
{
settings.CrossOriginResourcePolicy = CrossOriginResourcePolicy.same_origin;
});
{
"SecurityHeaders": {
"CrossOriginResourcePolicy": "same_origin"
}
}
Clear-Site-Data
You can configure Clear-Site-Data passing a configured ClearSitedata object. You can clear site data for cache, storage and cookies. The default value for the header is
Clear-Site-Data: "cache", "cookies", "storage"
app.UseSecurityHeaders(settings =>
{
settings.ClearSiteData = new ClearSitedata.ClearSiteData()
.ClearCache()
.ClearCookies()
.ClearStorage();
});
{
"SecurityHeaders": {
"ClearSiteData": [ "cache", "cookies" , "storage"]
}
}
Content-Security-Policy
You can configure Content-Security-Policy passing a configured ContentSecurityPolicy object. You can configure the object using configuration, using a "ready-to-use" string or using a ContentSecurityPolicyBuilder
with fluent API.
The default value for the header is:
Content-Security-Policy: default-src 'self'; object-src 'none'; child-src 'self'; frame-ancestors 'none'; upgrade-insecure-requests; block-all-mixed-content
//Configure CSP with a string
app.UseSecurityHeaders(settings =>
{
settings.ContentSecurityPolicy = ContentSecurityPolicyBuilder
.New("default-src 'self'; object-src 'none'")
.Build();
});
//Configure CSP with fluent API
app.UseSecurityHeaders(settings =>
{
settings.ContentSecurityPolicy = ContentSecurityPolicyBuilder
.New()
.AddDefaultSrc(directives => {
directives.Self();
directives.UnsafeInline();
directives.AddSource("https://github.com");
})
.Build();
});
//Disable CSP header
app.UseSecurityHeaders(settings =>
{
settings.UseContentSecurityPolicy = false;
});
If both a string and fluent API are used with ContentSecurityPolicyBuilder
the string take the precedence
{
"SecurityHeaders": {
"UseContentSecurityPolicy": true //set to false for disable header
"ContentSecurityPolicy": {
"default-src": [ "'self'" ],
"object-src": [ "'none'" ],
"block-all-mixed-content": [ "" ],
"child-src": [ "'self'" ],
"frame-ancestors": [ "'none'" ],
"upgrade-insecure-requests": [ "" ],
"style-src": [ "'self'", "https://fonts.googleapis.com", "'nonce'" ],
"font-src": [ "'self'", "https://fonts.gstatic.com" ],
"script-src": [ "'self'", "'nonce'" ],
"script-src-elem": [ "'self'", "'nonce'" ],
"connect-src": [ "'self'" ],
"prefetch-src": [ "'self'", "https://fonts.googleapis.com", "'nonce'" ]
}
}
}
Configure a directive calling the right method on the builder then adding all the allowed sources with AddSource()
. Some utility methods like All(), None(), Self(), UnsafeInline(), UnsafeEval()
can be used for standard values
If a directive take no extra values (like block-all-mixed-content) pass an array with an empty string in configuration file.
Nonce
If you need to use nonce for inline script and styles call AddSource("'nonce'")
in fluent API or use the string "'nonce'"
in configuration file.
Using nonce require that you configure a service for nonce generation in your startup file, so call the extension method:
services.AddNonceService();
The service inject a different nonce value in the header foreach request. Using this service you can easily build a TagHelper for RazorView pages:
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Razor.TagHelpers;
using QuokkaDev.SecurityHeaders;
namespace MyProject.Web.TagHelpers
{
[HtmlTargetElement(Attributes = "add-nonce")]
public class NonceTagHelper : TagHelper
{
private readonly IHttpContextAccessor _contextAccessor;
public NonceTagHelper(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.Attributes.RemoveAll("add-nonce");
output.Attributes.Add(new TagHelperAttribute("nonce", new HtmlString(_contextAccessor.GetNonce())));
}
}
}
<script type="text/javascript" add-nonce>
alert('now inline script works!!!');
</script>
Permissions-Policy
You can configure Permissions-Policy passing a configured PermissionPolicy object. You can configure the object using configuration, using a "ready-to-use" string or using a PermissionPolicyBuilder
with fluent API.
The default value for the header is:
Permissions-Policy: accelerometer=(),autoplay=(),camera=(),display-capture=(),document-domain=(),encrypted-media=(),fullscreen=(),geolocation=(),gyroscope=(),magnetometer=(),microphone=(),midi=(),payment=(),picture-in-picture=(),publickey-credentials-get=(),screen-wake-lock=(),sync-xhr=(self),usb=(),web-share=(),xr-spatial-tracking=()
//Configure permissions policy with a string
app.UseSecurityHeaders(settings =>
{
settings.PermissionPolicy = PermissionPolicyBuilder
.New("accelerometer=(),autoplay=(),camera=()")
.Build();
});
//Configure permissions policy with fluent API
app.UseSecurityHeaders(settings =>
{
settings.PermissionPolicy = PermissionPolicyBuilder
.New()
.AddCamera(directives => {
directives.Self();
})
.Build();
});
//Disable permissions policy header
app.UseSecurityHeaders(settings =>
{
settings.UsePermissionPolicy = false;
});
If both a string and fluent API are used with PermissionsPolicyBuilder
the string take the precedence
{
"SecurityHeaders": {
"UsePermissionPolicy": true //set to false for disable header
"PermissionPolicy": {
"accelerometer": [""],
"camera": [ "self" ],
"display-capture": ["self", "https://mydomain"]
}
}
}
Configure a directive calling the right method on the builder then adding all the allowed sources with AddSource()
. Utility method like Self()
can be used for 'self' standard value
If a directive take no extra values pass an array with an empty string in configuration file.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- Microsoft.AspNetCore.Http.Abstractions (>= 2.2.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 6.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 6.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 6.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 6.0.1)
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 |
---|---|---|
4.0.0 | 363 | 11/29/2023 |
4.0.0-rc4 | 105 | 11/29/2023 |
3.1.1-rc1 | 134 | 5/10/2023 |
3.1.0 | 1,031 | 12/21/2022 |
3.1.0-rc8 | 110 | 5/10/2023 |
3.1.0-rc7 | 147 | 12/21/2022 |
3.0.0 | 487 | 9/27/2022 |
3.0.0-rc6 | 174 | 9/27/2022 |
3.0.0-rc5 | 165 | 9/27/2022 |
3.0.0-alpha7 | 173 | 9/28/2022 |
2.1.1 | 423 | 9/12/2022 |
2.1.1-alpha8 | 184 | 9/27/2022 |
2.1.1-alpha0 | 155 | 9/13/2022 |
2.1.0 | 516 | 9/1/2022 |
2.1.0-alpha3 | 158 | 9/3/2022 |
2.0.0 | 399 | 8/29/2022 |
2.0.0-alpha2 | 172 | 9/2/2022 |
2.0.0-alpha0 | 149 | 8/30/2022 |
1.2.5 | 403 | 8/29/2022 |
1.2.4 | 408 | 8/25/2022 |
1.2.4-alpha0 | 163 | 8/26/2022 |
1.2.3 | 497 | 8/12/2022 |
1.2.3-alpha0 | 185 | 8/13/2022 |
1.2.2 | 427 | 8/12/2022 |
1.2.1 | 436 | 8/12/2022 |
1.2.0 | 440 | 8/12/2022 |
1.2.0-rc1 | 166 | 8/12/2022 |
1.1.1 | 440 | 8/11/2022 |
1.1.1-rc1 | 172 | 8/11/2022 |
1.1.1-alpha1 | 175 | 8/12/2022 |
1.1.0 | 412 | 8/11/2022 |
1.0.0 | 469 | 6/24/2022 |
1.0.0-alpha0 | 188 | 6/26/2022 |