Content Security Policy

Hello,

I'm using Radzen Blazor for a Blazor WASM PoC and so far it's seems pretty neat.

However, I have a problem setting the correct Content Security Policy header without resorting to 'unsafe-inline' directive. I would prefer a sha-256 or maybe a nonce if possible?

Microsoft has documented CSP for Blazor WASM here:

Thanks in advance for any help!

Hi @magnus,

I'm not sure I understand your question. You don't know where to declare the meta tag?

Thanks for the answer.

I set the header in web.config so that's not a problem, it's what least "priveledges" needed for Radzen to run.

For latest Radzen.Blazor.js the hash 'sha256-pRMAucOBdMdC2z5zEOUr2nMkyE9Y06L6PBeBKrjyKjY=' works.

But it's also running inline javascript sometimes (noticed on fileupload), and there I haven't been able to calculate a working hash. I'm not sure, maybe the inline script could come with a nonce set?

The Radzen Upload does not use inline script elements. The complete source is available here.

I investigated a little further. When I look at the generated code on the client/browser for RadzenUpload-input it looks like this:
<input id="450ce315-3e26-4920-a526-ed4b64aacac0" type="file" onchange="(function (e) { if (true) { Radzen.upload(e.target, '', false, true); e.target.value = ''; } else { Radzen.uploadChange(e.target) } })(event)" _bl_33="">

It's the onchange javascript that is inline as also seen in source code:

This results in "Refused to execute inline event handler because it violates the following Content Security Policy..." unless you set Content Security Policy to 'unsafe-inline'

This post explains the problem:

It would be great if this sort of javascript could be moved to the Radzen.Blazor.js (best) or an inline block with nonce (second best), otherwise users of Radzen Blazor won't be able to use without having unsafe Content Security Policy settings.

1 Like

Thanks for the investigation. We will consider your feedback for a future release of Radzen.Blazor. For now you would have to use unsafe-inline.

'nonce-value' is not applicable for Blazor WASM because of client side rendering. Nonces should be generated with fresh value each page loading. It's possible on server side only.
Also 'nonce-value' can be used only to allow inline scripts kind of <script>...</script>. But Radzen Blasor code use a lot of other kinds of inline scripts - inline event handlers in tags (you have found part of them) and also javascript:-navigation like href="javascript:void(0)", for example:
RadzenAccordion:
<a @onclick="@((args) => SelectItem(item))" href="javascript:void(0)" role="tab" tabindex="0"

RadzenPager:
<a class="rz-paginator-first rz-paginator-element" href="javascript:void(0)" tabindex="-1" @onclick="@(() => FirstPage())">

There is no way to avoid of using 'unsafe-inline' token, because of 'unsafe-hashes' token designed for these cases, is not supported by Safari.

The best you can do, it's to use the policy:

script-src 'self' 'unsafe-inline'; script-src-elem 'self' 'sha256-...' (all hashes here); script-src-attr 'unsafe-inline';

It will mitigate consequences of 'unsafe-inline' for Chrome browsers - injection of <script>...</script> will be prohibited. Firefox and Safari will follow script-src 'self' 'unsafe-inline' rule.

Also Radzen Blasor code use a lot of style= attributes in tags, therefore you have to use 'unsafe-inline' in style-src directive too.

Thanks, very informative! Content security policy is a bit tricky to get right...

Couldn't I make it:

script-src 'self'
'unsafe-eval';
script-src-elem 'self'
'sha256-...'
'sha256-...';
script-src-attr 'unsafe-inline';

With the 'unsafe-inline' removed from script-src?

With the 'unsafe-inline' removed from script-src?

No, Safari and Firefox do not support script-src-attr / script-src-elem directives, therefore they will use script-src. Without 'unsafe-inline' all inline scripts (event handlers in tags, javascript-navigation and <script>) will be blocked in Safari/Firefox.

script-src will apply for Safari and Firefox, and script-src-attr / script-src-elem - for Chrome. That's why Chrome users will be protected against XSS much better.

PS: why do you wish to add 'unsafe-eval'? You do use eval() or new Function() in the app?

Is there any update on this? It seems we still have to use script-src 'self' 'unsafe-inline'

No, there isn't an update. The changes required to support restrictive content policies are too broad for us to consider at this time. We would probably accept pull requests though as long as they:

  1. Don't overcomplicate the implementation
  2. Don't break existing functionality