'Dot Net 5 CSP with a nonce - discrepancy between nonce in header and nonce in script tags
I have a .Net 5 site and would like to implement a CSP using a nonce for scripts. I register ICspNonceService in my Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
...various services added
services.AddContentSecurityPolicyNonce();
}
Then I add my headers with some middleware
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
var nonceService = app.ApplicationServices.GetService(typeof(ICspNonceService));
app.UseSecurityHeadersMiddleware(new SecurityHeadersBuilder((ICspNonceService)nonceService).AddDefaultSecurePolicy().RemoveHeader("X-Powered-By"));
...various middleware
}
And in that middleware:
public SecurityHeadersBuilder AddContentSecurityPolicy()
{
var policy = new List<string>();
var contentSecurityPolicies = Enum.GetValues<ContentSecurityPolicy>();
foreach (var contentSecurityPolicy in contentSecurityPolicies)
{
var value = contentSecurityPolicy.Value();
if (!string.IsNullOrEmpty(value))
{
value = value.Replace("{nonceValue}", this._cspNonceService.GetNonce());
policy.Add(value);
}
}
this._policy.SetHeaders[ContentSecurityPolicyConstants.Header] = string.Join(';', policy.ToArray());
return this;
}
And this produces my appropriate header:
default-src 'self'; script-src 'nonce-h5BUValX03OJFO165044o1gMNVUMsbhdYUvzpDATneU=' 'strict-dynamic'
Then I have a taghelper to add my nonce to a script tag:
[HtmlTargetElement("script", Attributes = "use-csp-nonce")]
public class NonceTagHelper : TagHelper
{
private readonly ICspNonceService _nonceService;
public NonceTagHelper(ICspNonceService nonceService) => this._nonceService = nonceService;
[HtmlAttributeName("use-csp-nonce")]
public bool UseNonce { get; set; }
public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
if (this.UseNonce)
{
output.Attributes.SetAttribute("nonce", this._nonceService.GetNonce());
}
return base.ProcessAsync(context, output);
}
}
Which I can use like this:
<script use-csp-nonce="true" src="/dist/js/main.min.js" asp-append-version="true" ></script>
This produces a script tag with a nonce, but it is not the same nonce as the header, so it all fails.
I have several theories:
- Something about the order of my services registrations
- The way I am injecting the ICspNonceService for the header
How do I ensure I get the same Nonce?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
