QuokkaDev.SecurityHeaders 1.2.4

There is a newer version of this package available.
See the version list below for details.
dotnet add package QuokkaDev.SecurityHeaders --version 1.2.4                
NuGet\Install-Package QuokkaDev.SecurityHeaders -Version 1.2.4                
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="QuokkaDev.SecurityHeaders" Version="1.2.4" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add QuokkaDev.SecurityHeaders --version 1.2.4                
#r "nuget: QuokkaDev.SecurityHeaders, 1.2.4"                
#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.
// Install QuokkaDev.SecurityHeaders as a Cake Addin
#addin nuget:?package=QuokkaDev.SecurityHeaders&version=1.2.4

// Install QuokkaDev.SecurityHeaders as a Cake Tool
#tool nuget:?package=QuokkaDev.SecurityHeaders&version=1.2.4                

Quality Gate Status Coverage Maintainability Rating Technical Debt Duplicated Lines (%) publish workflow

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 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. 
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
4.0.0 365 11/29/2023
4.0.0-rc4 107 11/29/2023
3.1.1-rc1 136 5/10/2023
3.1.0 1,033 12/21/2022
3.1.0-rc8 112 5/10/2023
3.1.0-rc7 149 12/21/2022
3.0.0 489 9/27/2022
3.0.0-rc6 176 9/27/2022
3.0.0-rc5 167 9/27/2022
3.0.0-alpha7 175 9/28/2022
2.1.1 425 9/12/2022
2.1.1-alpha8 186 9/27/2022
2.1.1-alpha0 157 9/13/2022
2.1.0 518 9/1/2022
2.1.0-alpha3 160 9/3/2022
2.0.0 401 8/29/2022
2.0.0-alpha2 174 9/2/2022
2.0.0-alpha0 151 8/30/2022
1.2.5 405 8/29/2022
1.2.4 410 8/25/2022
1.2.4-alpha0 165 8/26/2022
1.2.3 499 8/12/2022
1.2.3-alpha0 187 8/13/2022
1.2.2 429 8/12/2022
1.2.1 438 8/12/2022
1.2.0 442 8/12/2022
1.2.0-rc1 168 8/12/2022
1.1.1 442 8/11/2022
1.1.1-rc1 174 8/11/2022
1.1.1-alpha1 177 8/12/2022
1.1.0 414 8/11/2022
1.0.0 471 6/24/2022
1.0.0-alpha0 190 6/26/2022