andrewlock / NetEscapades.AspNetCore.SecurityHeaders

Small package to allow adding security headers to ASP.NET Core websites
MIT License
695 stars 73 forks source link

Adding `strict-dynamic` to a Script CSP breaks nonce tag helpers #65

Closed garethterrace closed 5 years ago

garethterrace commented 5 years ago

Okay so this might be user error, but I have a test page with the following scripts:

<script nonce="@Context.GetNonce()">
            console.log("JS running with an injected nonce");
</script> 

<script asp-add-nonce>
            console.log("JS running with a tag helper nonce");
</script>

<script asp-add-content-to-csp csp-hash-type="SHA384">
            console.log("JS running with the hashtags");
</script>

Just as tests for whether the CSP is allowing scripts with nonces to run.

If my CSP is set as follows:

.AddContentSecurityPolicy(builder =>
                {
                    builder.AddUpgradeInsecureRequests();

                    builder.AddObjectSrc().None();

                    builder.AddScriptSrc()
                        .Self()
                        .UnsafeInline()
                        .StrictDynamic()
                        .WithHashTagHelper();

                    builder.AddBaseUri().None();

                    builder.AddReportUri().To("/csp/report");

                });

Nothing loads.

If I remove the StrictDynamic() part, things start working again and those three scripts run.

Am I doing something stupid, or are the taghelpers not running for strict dynamic?

andrewlock commented 5 years ago

Hi,

I think this is likely an issue with the CSP directive itself (and the brower's handling of it), rather than the library.

Please check the CSP returned by your app - I think you'll find the issue is related to interactions between the multiple script-src directives rather than the library 🙂

garethterrace commented 5 years ago

From what I can see, the CSP is returning okay.

Setting up these directives:

 .AddContentSecurityPolicy(csp =>
                {
                    csp.AddUpgradeInsecureRequests();

                    csp.AddObjectSrc().None();

                    csp.AddScriptSrc()
                        .Self()
                        .UnsafeInline()
                        .StrictDynamic()
                        .WithNonce()
                        .WithHashTagHelper();

                    csp.AddStyleSrc()
                        .Self()
                        .UnsafeInline();

                    csp.AddBaseUri().None();

                });

Returns this CSP: image

If I use Context.GetNonce() I can load scripts, but if I use asp-add-nonce nothing gets injected. It's almost like the TagHelpers can't see the nonce or aren't "active" somehow: image

Sorry if this isn't very clear, or I've fundamentally misunderstood something here. I'm following Google's Strict CSP Guide and the TagHelpers would make integrating nonces in the app much nicer

andrewlock commented 5 years ago

It's almost like the TagHelpers can't see the nonce or aren't "active" somehow:

Ah, you've hit the nail on the head there! The tag helpers aren't running, which is why you see asp-add-nonce in the HTML.

When you use Tag Helpers, you need to import them in your _ViewImports.cshtml file using @addTagHelper

So for the nonce tag helpers to work, you need to add:

@addTagHelper *, NetEscapades.AspNetCore.SecurityHeaders.TagHelpers

as I have in this sample.

Give that a try, hopefully it works. This should be in the documentation, so 100% not your fault! 🙂

garethterrace commented 5 years ago

Ah sorry, forgot to mention I've done that this afternoon and still no dice!

Edit: It's working fine on a new test project but not my actual app, I'll sleep on it and close this is if it's fixed it tomorrow

andrewlock commented 5 years ago

Hmmm, that is odd. Are you sure you're referencing the SecurityHeaders.TagHelpers package in your app, not just the main SecurityHeaders package?

garethterrace commented 5 years ago

Update: Yes, sorted - turns out I can't type. I had add-asp-nonce.

Long day! Thanks for your help!